
kernel.elf:     file format elf64-littleriscv


Disassembly of section .text:

0000000080000000 <_start>:
.section .text.start
.global _start
_start:
    # 1. 设置栈指针
    la sp, stack_top        # stack_top在链接脚本中定义
    80000000:	00004117          	auipc	sp,0x4
    80000004:	00010113          	mv	sp,sp

    # 2. 调试：输出'S'（启动标记）
    li t0, 0x10000000       # UART基地址
    80000008:	100002b7          	lui	t0,0x10000
    li t1, 'S'
    8000000c:	05300313          	li	t1,83
    sb t1, 0(t0)
    80000010:	00628023          	sb	t1,0(t0) # 10000000 <_start-0x70000000>

    # 3. 清零BSS段
    la a0, _bss_start       # BSS起始地址（链接脚本定义）
    80000014:	00002517          	auipc	a0,0x2
    80000018:	65450513          	add	a0,a0,1620 # 80002668 <pmm>
    la a1, _end             # BSS结束地址
    8000001c:	00002597          	auipc	a1,0x2
    80000020:	67c58593          	add	a1,a1,1660 # 80002698 <_end>
    j bss_zero_loop
    80000024:	a009                	j	80000026 <bss_zero_loop>

0000000080000026 <bss_zero_loop>:
bss_zero_loop:
    bge a0, a1, bss_done    # 若a0 >= a1，跳转至bss_done
    80000026:	00b55663          	bge	a0,a1,80000032 <bss_done>
    sd zero, 0(a0)          # 写0至当前地址
    8000002a:	00053023          	sd	zero,0(a0)
    addi a0, a0, 8          # 地址递增8字节
    8000002e:	0521                	add	a0,a0,8
    j bss_zero_loop
    80000030:	bfdd                	j	80000026 <bss_zero_loop>

0000000080000032 <bss_done>:
bss_done:

    # 4. 调试：输出'P'（栈设置完成）
    li t1, 'P'
    80000032:	05000313          	li	t1,80
    sb t1, 0(t0)
    80000036:	00628023          	sb	t1,0(t0)

    # 5. 跳转至C主函数
    #  实验一：call start
    # 实验二
    call main
    8000003a:	006000ef          	jal	80000040 <main>

000000008000003e <spin>:
spin:
    j spin                  # 主函数返回则死循环
    8000003e:	a001                	j	8000003e <spin>

0000000080000040 <main>:
#include "ansi.h"
#include "pmm.h"
#include "test_mem.h"

int main(void)
{
    80000040:	1141                	add	sp,sp,-16 # 80003ff0 <stack_bottom+0xff0>
    80000042:	e406                	sd	ra,8(sp)
    80000044:	e022                	sd	s0,0(sp)
    80000046:	0800                	add	s0,sp,16
    // 早期初始化
    uart_init();     // 串口初始化
    80000048:	036000ef          	jal	8000007e <uart_init>
    printf("=== Kernel Starting ===\n");
    8000004c:	00002517          	auipc	a0,0x2
    80000050:	fb450513          	add	a0,a0,-76 # 80002000 <_etext>
    80000054:	376000ef          	jal	800003ca <printf>
    //pmm_init();     // 物理内存管理器初始化
    printf("=== PMM Initialized ===\n"); 
    80000058:	00002517          	auipc	a0,0x2
    8000005c:	fc850513          	add	a0,a0,-56 # 80002020 <_etext+0x20>
    80000060:	36a000ef          	jal	800003ca <printf>
    
    // 运行测试
    //test_physical_memory();
    //test_pagetable(); 
    test_virtual_memory();
    80000064:	5a9000ef          	jal	80000e0c <test_virtual_memory>
    
    printf("All memory management tests passed!\n");
    80000068:	00002517          	auipc	a0,0x2
    8000006c:	fd850513          	add	a0,a0,-40 # 80002040 <_etext+0x40>
    80000070:	35a000ef          	jal	800003ca <printf>
    
    // 进入主循环
    for(;;) {
        asm volatile("wfi"); // 等待中断
    80000074:	10500073          	wfi
    80000078:	10500073          	wfi
    for(;;) {
    8000007c:	bfe5                	j	80000074 <main+0x34>

000000008000007e <uart_init>:
#define UART_LSR_RX_READY (1 << 0)   // 数据就绪
#define UART_LSR_TX_EMPTY (1 << 5)   // 发送器空
#define UART_LSR_TX_IDLE  (1 << 6)   // 发送器空闲

// 初始化UART
void uart_init(void) {
    8000007e:	1141                	add	sp,sp,-16
    80000080:	e422                	sd	s0,8(sp)
    80000082:	0800                	add	s0,sp,16
    // 禁用中断
    *UART_REG(UART_IER) = 0x00;
    80000084:	100007b7          	lui	a5,0x10000
    80000088:	000780a3          	sb	zero,1(a5) # 10000001 <_start-0x6fffffff>
    
    // 设置波特率 (115200)
    *UART_REG(UART_LCR) = 0x80;  // 启用DLAB
    8000008c:	f8000713          	li	a4,-128
    80000090:	00e781a3          	sb	a4,3(a5)
    *UART_REG(UART_THR) = 0x01;  // 分频低字节
    80000094:	4705                	li	a4,1
    80000096:	00e78023          	sb	a4,0(a5)
    *UART_REG(UART_IER) = 0x00;  // 分频高字节
    8000009a:	000780a3          	sb	zero,1(a5)
    
    // 8N1格式，禁用DLAB
    *UART_REG(UART_LCR) = 0x03;
    8000009e:	468d                	li	a3,3
    800000a0:	00d781a3          	sb	a3,3(a5)
    
    // 启用FIFO，清除它们，设置14字节阈值
    *UART_REG(UART_FCR) = 0xC7;
    800000a4:	fc700693          	li	a3,-57
    800000a8:	00d78123          	sb	a3,2(a5)
    
    // 启用中断
    *UART_REG(UART_IER) = 0x01;
    800000ac:	00e780a3          	sb	a4,1(a5)
}
    800000b0:	6422                	ld	s0,8(sp)
    800000b2:	0141                	add	sp,sp,16
    800000b4:	8082                	ret

00000000800000b6 <uart_putc>:
static int uart_can_send(void) {
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
}

// 等待并发送一个字符
void uart_putc(char c) {
    800000b6:	1141                	add	sp,sp,-16
    800000b8:	e422                	sd	s0,8(sp)
    800000ba:	0800                	add	s0,sp,16
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
    800000bc:	10000737          	lui	a4,0x10000
    
    // 发送字符
    *UART_REG(UART_THR) = c;
    
    // 如果是换行，还需要发送回车
    if (c == '\n') {
    800000c0:	46a9                	li	a3,10
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
    800000c2:	00574783          	lbu	a5,5(a4) # 10000005 <_start-0x6ffffffb>
    while (!uart_can_send()) {
    800000c6:	0407f793          	and	a5,a5,64
    800000ca:	dfe5                	beqz	a5,800000c2 <uart_putc+0xc>
    *UART_REG(UART_THR) = c;
    800000cc:	00a70023          	sb	a0,0(a4)
    if (c == '\n') {
    800000d0:	00d51463          	bne	a0,a3,800000d8 <uart_putc+0x22>
        uart_putc('\r');
    800000d4:	4535                	li	a0,13
    while (!uart_can_send()) {
    800000d6:	b7f5                	j	800000c2 <uart_putc+0xc>
    }
}
    800000d8:	6422                	ld	s0,8(sp)
    800000da:	0141                	add	sp,sp,16
    800000dc:	8082                	ret

00000000800000de <uart_puts>:

// 批量发送字符串
void uart_puts(const char *str) {
    800000de:	1141                	add	sp,sp,-16
    800000e0:	e422                	sd	s0,8(sp)
    800000e2:	0800                	add	s0,sp,16
    while (*str) {
    800000e4:	00054683          	lbu	a3,0(a0)
    800000e8:	c685                	beqz	a3,80000110 <uart_puts+0x32>
    800000ea:	85aa                	mv	a1,a0
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
    800000ec:	10000737          	lui	a4,0x10000
    if (c == '\n') {
    800000f0:	4629                	li	a2,10
        uart_putc(*str++);
    800000f2:	0585                	add	a1,a1,1
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
    800000f4:	00574783          	lbu	a5,5(a4) # 10000005 <_start-0x6ffffffb>
    while (!uart_can_send()) {
    800000f8:	0407f793          	and	a5,a5,64
    800000fc:	dfe5                	beqz	a5,800000f4 <uart_puts+0x16>
    *UART_REG(UART_THR) = c;
    800000fe:	00d70023          	sb	a3,0(a4)
    if (c == '\n') {
    80000102:	00c69463          	bne	a3,a2,8000010a <uart_puts+0x2c>
        uart_putc('\r');
    80000106:	46b5                	li	a3,13
    while (!uart_can_send()) {
    80000108:	b7f5                	j	800000f4 <uart_puts+0x16>
    while (*str) {
    8000010a:	0005c683          	lbu	a3,0(a1)
    8000010e:	f2f5                	bnez	a3,800000f2 <uart_puts+0x14>
    }
}
    80000110:	6422                	ld	s0,8(sp)
    80000112:	0141                	add	sp,sp,16
    80000114:	8082                	ret

0000000080000116 <uart_can_recv>:

// 检查是否有数据可读
int uart_can_recv(void) {
    80000116:	1141                	add	sp,sp,-16
    80000118:	e422                	sd	s0,8(sp)
    8000011a:	0800                	add	s0,sp,16
    return *UART_REG(UART_LSR) & UART_LSR_RX_READY;
    8000011c:	100007b7          	lui	a5,0x10000
    80000120:	0057c503          	lbu	a0,5(a5) # 10000005 <_start-0x6ffffffb>
}
    80000124:	6422                	ld	s0,8(sp)
    80000126:	8905                	and	a0,a0,1
    80000128:	0141                	add	sp,sp,16
    8000012a:	8082                	ret

000000008000012c <uart_getc>:

// 读取一个字符
char uart_getc(void) {
    8000012c:	1141                	add	sp,sp,-16
    8000012e:	e422                	sd	s0,8(sp)
    80000130:	0800                	add	s0,sp,16
    return *UART_REG(UART_LSR) & UART_LSR_RX_READY;
    80000132:	10000737          	lui	a4,0x10000
    80000136:	00574783          	lbu	a5,5(a4) # 10000005 <_start-0x6ffffffb>
    while (!uart_can_recv()) {
    8000013a:	8b85                	and	a5,a5,1
    8000013c:	dfed                	beqz	a5,80000136 <uart_getc+0xa>
        // 忙等待
    }
    return *UART_REG(UART_RHR);
}
    8000013e:	6422                	ld	s0,8(sp)
    return *UART_REG(UART_RHR);
    80000140:	00074503          	lbu	a0,0(a4)
}
    80000144:	0141                	add	sp,sp,16
    80000146:	8082                	ret

0000000080000148 <console_putc>:
#include "uart.h"
#include "defs.h"
#include "param.h"

// 简单的控制台输出
void console_putc(char c) {
    80000148:	1141                	add	sp,sp,-16
    8000014a:	e422                	sd	s0,8(sp)
    8000014c:	0800                	add	s0,sp,16
    uart_putc(c);
}
    8000014e:	6422                	ld	s0,8(sp)
    80000150:	0141                	add	sp,sp,16
    uart_putc(c);
    80000152:	b795                	j	800000b6 <uart_putc>

0000000080000154 <console_puts>:

void console_puts(const char *s) {
    80000154:	1141                	add	sp,sp,-16
    80000156:	e422                	sd	s0,8(sp)
    80000158:	0800                	add	s0,sp,16
    uart_puts(s);
}
    8000015a:	6422                	ld	s0,8(sp)
    8000015c:	0141                	add	sp,sp,16
    uart_puts(s);
    8000015e:	b741                	j	800000de <uart_puts>

0000000080000160 <console_write>:

void console_write(const char *buf, int n) {
    for (int i = 0; i < n; i++) {
    80000160:	02b05863          	blez	a1,80000190 <console_write+0x30>
void console_write(const char *buf, int n) {
    80000164:	1101                	add	sp,sp,-32
    80000166:	e822                	sd	s0,16(sp)
    80000168:	e426                	sd	s1,8(sp)
    8000016a:	e04a                	sd	s2,0(sp)
    8000016c:	ec06                	sd	ra,24(sp)
    8000016e:	1000                	add	s0,sp,32
    80000170:	84aa                	mv	s1,a0
    80000172:	00b50933          	add	s2,a0,a1
    uart_putc(c);
    80000176:	0004c503          	lbu	a0,0(s1)
    for (int i = 0; i < n; i++) {
    8000017a:	0485                	add	s1,s1,1
    uart_putc(c);
    8000017c:	f3bff0ef          	jal	800000b6 <uart_putc>
    for (int i = 0; i < n; i++) {
    80000180:	ff249be3          	bne	s1,s2,80000176 <console_write+0x16>
        console_putc(buf[i]);
    }
}
    80000184:	60e2                	ld	ra,24(sp)
    80000186:	6442                	ld	s0,16(sp)
    80000188:	64a2                	ld	s1,8(sp)
    8000018a:	6902                	ld	s2,0(sp)
    8000018c:	6105                	add	sp,sp,32
    8000018e:	8082                	ret
    80000190:	8082                	ret

0000000080000192 <console_readline>:

// 读取一行输入（简单的行编辑）
void console_readline(char *buf, int max_len) {
    80000192:	711d                	add	sp,sp,-96
    80000194:	e8a2                	sd	s0,80(sp)
    80000196:	e4a6                	sd	s1,72(sp)
    80000198:	e0ca                	sd	s2,64(sp)
    8000019a:	fc4e                	sd	s3,56(sp)
    8000019c:	f852                	sd	s4,48(sp)
    8000019e:	f456                	sd	s5,40(sp)
    800001a0:	f05a                	sd	s6,32(sp)
    800001a2:	ec5e                	sd	s7,24(sp)
    800001a4:	e862                	sd	s8,16(sp)
    800001a6:	e466                	sd	s9,8(sp)
    800001a8:	ec86                	sd	ra,88(sp)
    800001aa:	e06a                	sd	s10,0(sp)
    800001ac:	1080                	add	s0,sp,96
    800001ae:	8aaa                	mv	s5,a0
    int pos = 0;
    800001b0:	4481                	li	s1,0
    
    while (1) {
        c = uart_getc();
        
        // 回车键结束输入
        if (c == '\r' || c == '\n') {
    800001b2:	4935                	li	s2,13
    800001b4:	49a9                	li	s3,10
            buf[pos] = '\0';
            return;
        }
        
        // 退格键处理
        if (c == '\b' || c == 127) {
    800001b6:	4a21                	li	s4,8
    uart_puts(s);
    800001b8:	00002c17          	auipc	s8,0x2
    800001bc:	eb0c0c13          	add	s8,s8,-336 # 80002068 <_etext+0x68>
        if (c == '\b' || c == 127) {
    800001c0:	07f00b93          	li	s7,127
            }
            continue;
        }
        
        // 普通字符
        if (pos < max_len - 1 && c >= 32 && c <= 126) {
    800001c4:	fff58b1b          	addw	s6,a1,-1
    800001c8:	05e00c93          	li	s9,94
        c = uart_getc();
    800001cc:	f61ff0ef          	jal	8000012c <uart_getc>
        if (c == '\r' || c == '\n') {
    800001d0:	03250d63          	beq	a0,s2,8000020a <console_readline+0x78>
    800001d4:	03350b63          	beq	a0,s3,8000020a <console_readline+0x78>
        if (c == '\b' || c == 127) {
    800001d8:	05450d63          	beq	a0,s4,80000232 <console_readline+0xa0>
    800001dc:	05750b63          	beq	a0,s7,80000232 <console_readline+0xa0>
        if (pos < max_len - 1 && c >= 32 && c <= 126) {
    800001e0:	fe05071b          	addw	a4,a0,-32
    800001e4:	0ff77713          	zext.b	a4,a4
    800001e8:	ff64d2e3          	bge	s1,s6,800001cc <console_readline+0x3a>
            buf[pos++] = c;
    800001ec:	009a86b3          	add	a3,s5,s1
    800001f0:	00148d1b          	addw	s10,s1,1
        if (pos < max_len - 1 && c >= 32 && c <= 126) {
    800001f4:	fcecece3          	bltu	s9,a4,800001cc <console_readline+0x3a>
            buf[pos++] = c;
    800001f8:	00a68023          	sb	a0,0(a3)
    uart_putc(c);
    800001fc:	ebbff0ef          	jal	800000b6 <uart_putc>
            buf[pos++] = c;
    80000200:	84ea                	mv	s1,s10
        c = uart_getc();
    80000202:	f2bff0ef          	jal	8000012c <uart_getc>
        if (c == '\r' || c == '\n') {
    80000206:	fd2517e3          	bne	a0,s2,800001d4 <console_readline+0x42>
            buf[pos] = '\0';
    8000020a:	9aa6                	add	s5,s5,s1
    uart_putc(c);
    8000020c:	4529                	li	a0,10
    8000020e:	ea9ff0ef          	jal	800000b6 <uart_putc>
            buf[pos] = '\0';
    80000212:	000a8023          	sb	zero,0(s5)
            console_putc(c);
        }
    }
}
    80000216:	60e6                	ld	ra,88(sp)
    80000218:	6446                	ld	s0,80(sp)
    8000021a:	64a6                	ld	s1,72(sp)
    8000021c:	6906                	ld	s2,64(sp)
    8000021e:	79e2                	ld	s3,56(sp)
    80000220:	7a42                	ld	s4,48(sp)
    80000222:	7aa2                	ld	s5,40(sp)
    80000224:	7b02                	ld	s6,32(sp)
    80000226:	6be2                	ld	s7,24(sp)
    80000228:	6c42                	ld	s8,16(sp)
    8000022a:	6ca2                	ld	s9,8(sp)
    8000022c:	6d02                	ld	s10,0(sp)
    8000022e:	6125                	add	sp,sp,96
    80000230:	8082                	ret
    uart_puts(s);
    80000232:	8562                	mv	a0,s8
            if (pos > 0) {
    80000234:	dcc1                	beqz	s1,800001cc <console_readline+0x3a>
                pos--;
    80000236:	34fd                	addw	s1,s1,-1
    uart_puts(s);
    80000238:	ea7ff0ef          	jal	800000de <uart_puts>
}
    8000023c:	bf41                	j	800001cc <console_readline+0x3a>

000000008000023e <cprintf>:

// 控制台输出（带颜色支持）
void cprintf(const char* fmt, ...) {
    8000023e:	715d                	add	sp,sp,-80
    80000240:	e422                	sd	s0,8(sp)
    80000242:	0800                	add	s0,sp,16
    
    // 简化实现示例：
    volatile unsigned int* uart_tx = (unsigned int*)0x10000000; // UART地址
    const char* p = fmt;
    
    while (*p) {
    80000244:	00054303          	lbu	t1,0(a0)
void cprintf(const char* fmt, ...) {
    80000248:	e40c                	sd	a1,8(s0)
    8000024a:	e810                	sd	a2,16(s0)
    8000024c:	ec14                	sd	a3,24(s0)
    8000024e:	f018                	sd	a4,32(s0)
    80000250:	f41c                	sd	a5,40(s0)
    80000252:	03043823          	sd	a6,48(s0)
    80000256:	03143c23          	sd	a7,56(s0)
    while (*p) {
    8000025a:	00030c63          	beqz	t1,80000272 <cprintf+0x34>
        *uart_tx = *p++; // 输出字符到UART
    8000025e:	100007b7          	lui	a5,0x10000
    80000262:	2301                	sext.w	t1,t1
    80000264:	0505                	add	a0,a0,1
    80000266:	0067a023          	sw	t1,0(a5) # 10000000 <_start-0x70000000>
    while (*p) {
    8000026a:	00054303          	lbu	t1,0(a0)
    8000026e:	fe031ae3          	bnez	t1,80000262 <cprintf+0x24>
    }
}
    80000272:	6422                	ld	s0,8(sp)
    80000274:	6161                	add	sp,sp,80
    80000276:	8082                	ret

0000000080000278 <panic>:

// 内核恐慌处理
void panic(const char* s) {
    80000278:	1141                	add	sp,sp,-16
    8000027a:	e422                	sd	s0,8(sp)
    8000027c:	0800                	add	s0,sp,16
    while (*p) {
    8000027e:	06b00793          	li	a5,107
    const char* p = fmt;
    80000282:	00002717          	auipc	a4,0x2
    80000286:	dee70713          	add	a4,a4,-530 # 80002070 <_etext+0x70>
        *uart_tx = *p++; // 输出字符到UART
    8000028a:	100006b7          	lui	a3,0x10000
    8000028e:	2781                	sext.w	a5,a5
    80000290:	0705                	add	a4,a4,1
    80000292:	c29c                	sw	a5,0(a3)
    while (*p) {
    80000294:	00074783          	lbu	a5,0(a4)
    80000298:	fbfd                	bnez	a5,8000028e <panic+0x16>
    cprintf("kernel panic: %s\n", s);
    
    // 禁用中断并进入无限循环
    asm volatile("csrc sstatus, %0" : : "r"(0x8)); // 清除SIE位
    8000029a:	47a1                	li	a5,8
    8000029c:	1007b073          	csrc	sstatus,a5
    for(;;) {
        asm volatile("wfi"); // 等待中断
    800002a0:	10500073          	wfi
    800002a4:	10500073          	wfi
    for(;;) {
    800002a8:	bfe5                	j	800002a0 <panic+0x28>

00000000800002aa <vprintf>:
void print_int(int num);
void print_uint(unsigned int num, int base, int uppercase);
void print_pointer(uintptr_t ptr);

// 简单的格式化输出实现
int vprintf(const char *fmt, va_list ap) {
    800002aa:	715d                	add	sp,sp,-80
    800002ac:	e0a2                	sd	s0,64(sp)
    800002ae:	f84a                	sd	s2,48(sp)
    800002b0:	e486                	sd	ra,72(sp)
    800002b2:	fc26                	sd	s1,56(sp)
    800002b4:	f44e                	sd	s3,40(sp)
    800002b6:	f052                	sd	s4,32(sp)
    800002b8:	ec56                	sd	s5,24(sp)
    800002ba:	e85a                	sd	s6,16(sp)
    800002bc:	e45e                	sd	s7,8(sp)
    800002be:	e062                	sd	s8,0(sp)
    800002c0:	0880                	add	s0,sp,80
    800002c2:	892a                	mv	s2,a0
    int chars_printed = 0;
    
    for (int i = 0; fmt[i]; i++) {
    800002c4:	00054503          	lbu	a0,0(a0)
    800002c8:	0e050f63          	beqz	a0,800003c6 <vprintf+0x11c>
    800002cc:	84ae                	mv	s1,a1
    800002ce:	4b81                	li	s7,0
    int chars_printed = 0;
    800002d0:	4a01                	li	s4,0
        if (fmt[i] == '%') {
    800002d2:	02500993          	li	s3,37
            i++;  // 跳过 '%'
            
            switch (fmt[i]) {
    800002d6:	02000b13          	li	s6,32
    800002da:	00002a97          	auipc	s5,0x2
    800002de:	db6a8a93          	add	s5,s5,-586 # 80002090 <_etext+0x90>
        if (fmt[i] == '%') {
    800002e2:	03351463          	bne	a0,s3,8000030a <vprintf+0x60>
            i++;  // 跳过 '%'
    800002e6:	2b85                	addw	s7,s7,1
            switch (fmt[i]) {
    800002e8:	01790c33          	add	s8,s2,s7
    800002ec:	000c4783          	lbu	a5,0(s8)
    800002f0:	0d378063          	beq	a5,s3,800003b0 <vprintf+0x106>
    800002f4:	fa87879b          	addw	a5,a5,-88
    800002f8:	0ff7f793          	zext.b	a5,a5
    800002fc:	02fb6d63          	bltu	s6,a5,80000336 <vprintf+0x8c>
    80000300:	078a                	sll	a5,a5,0x2
    80000302:	97d6                	add	a5,a5,s5
    80000304:	439c                	lw	a5,0(a5)
    80000306:	97d6                	add	a5,a5,s5
    80000308:	8782                	jr	a5
                    chars_printed += 2;
                    break;
                }
            }
        } else {
            console_putc(fmt[i]);
    8000030a:	e3fff0ef          	jal	80000148 <console_putc>
            chars_printed++;
    8000030e:	2a05                	addw	s4,s4,1
    for (int i = 0; fmt[i]; i++) {
    80000310:	2b85                	addw	s7,s7,1
    80000312:	017907b3          	add	a5,s2,s7
    80000316:	0007c503          	lbu	a0,0(a5)
    8000031a:	f561                	bnez	a0,800002e2 <vprintf+0x38>
        }
    }
    
    return chars_printed;
}
    8000031c:	60a6                	ld	ra,72(sp)
    8000031e:	6406                	ld	s0,64(sp)
    80000320:	74e2                	ld	s1,56(sp)
    80000322:	7942                	ld	s2,48(sp)
    80000324:	79a2                	ld	s3,40(sp)
    80000326:	6ae2                	ld	s5,24(sp)
    80000328:	6b42                	ld	s6,16(sp)
    8000032a:	6ba2                	ld	s7,8(sp)
    8000032c:	6c02                	ld	s8,0(sp)
    8000032e:	8552                	mv	a0,s4
    80000330:	7a02                	ld	s4,32(sp)
    80000332:	6161                	add	sp,sp,80
    80000334:	8082                	ret
                    console_putc('%');
    80000336:	02500513          	li	a0,37
    8000033a:	e0fff0ef          	jal	80000148 <console_putc>
                    console_putc(fmt[i]);
    8000033e:	000c4503          	lbu	a0,0(s8)
                    chars_printed += 2;
    80000342:	2a09                	addw	s4,s4,2
                    console_putc(fmt[i]);
    80000344:	e05ff0ef          	jal	80000148 <console_putc>
                    break;
    80000348:	b7e1                	j	80000310 <vprintf+0x66>
                    print_int(num);
    8000034a:	4088                	lw	a0,0(s1)
                    int num = va_arg(ap, int);
    8000034c:	04a1                	add	s1,s1,8
                    print_int(num);
    8000034e:	294000ef          	jal	800005e2 <print_int>
                    break;
    80000352:	bf7d                	j	80000310 <vprintf+0x66>
                    print_uint(num, 8, 1);
    80000354:	4088                	lw	a0,0(s1)
    80000356:	4605                	li	a2,1
    80000358:	45a1                	li	a1,8
                    unsigned int num = va_arg(ap, unsigned int);
    8000035a:	04a1                	add	s1,s1,8
                    print_uint(num, 8, 1);
    8000035c:	372000ef          	jal	800006ce <print_uint>
                    break;
    80000360:	bf45                	j	80000310 <vprintf+0x66>
                    console_putc(c);
    80000362:	0004c503          	lbu	a0,0(s1)
                    chars_printed++;
    80000366:	2a05                	addw	s4,s4,1
                    char c = (char)va_arg(ap, int);
    80000368:	04a1                	add	s1,s1,8
                    console_putc(c);
    8000036a:	ddfff0ef          	jal	80000148 <console_putc>
                    break;
    8000036e:	b74d                	j	80000310 <vprintf+0x66>
                    print_uint(num, 16, 1);
    80000370:	4088                	lw	a0,0(s1)
    80000372:	4605                	li	a2,1
    80000374:	45c1                	li	a1,16
                    unsigned int num = va_arg(ap, unsigned int);
    80000376:	04a1                	add	s1,s1,8
                    print_uint(num, 16, 1);
    80000378:	356000ef          	jal	800006ce <print_uint>
                    break;
    8000037c:	bf51                	j	80000310 <vprintf+0x66>
                    print_uint(num, 16, 0);
    8000037e:	4088                	lw	a0,0(s1)
    80000380:	4601                	li	a2,0
    80000382:	45c1                	li	a1,16
                    unsigned int num = va_arg(ap, unsigned int);
    80000384:	04a1                	add	s1,s1,8
                    print_uint(num, 16, 0);
    80000386:	348000ef          	jal	800006ce <print_uint>
                    break;
    8000038a:	b759                	j	80000310 <vprintf+0x66>
                    print_uint(num, 10, 1);
    8000038c:	4088                	lw	a0,0(s1)
    8000038e:	4605                	li	a2,1
    80000390:	45a9                	li	a1,10
                    unsigned int num = va_arg(ap, unsigned int);
    80000392:	04a1                	add	s1,s1,8
                    print_uint(num, 10, 1);
    80000394:	33a000ef          	jal	800006ce <print_uint>
                    break;
    80000398:	bfa5                	j	80000310 <vprintf+0x66>
                    char *str = va_arg(ap, char*);
    8000039a:	6088                	ld	a0,0(s1)
    8000039c:	04a1                	add	s1,s1,8
                    if (!str) str = "(null)";
    8000039e:	cd19                	beqz	a0,800003bc <vprintf+0x112>
                    console_puts(str);
    800003a0:	db5ff0ef          	jal	80000154 <console_puts>
                    break;
    800003a4:	b7b5                	j	80000310 <vprintf+0x66>
                    print_pointer((uintptr_t)ptr);
    800003a6:	4088                	lw	a0,0(s1)
                    void *ptr = va_arg(ap, void*);
    800003a8:	04a1                	add	s1,s1,8
                    print_pointer((uintptr_t)ptr);
    800003aa:	3c0000ef          	jal	8000076a <print_pointer>
                    break;
    800003ae:	b78d                	j	80000310 <vprintf+0x66>
                    console_putc('%');
    800003b0:	02500513          	li	a0,37
    800003b4:	d95ff0ef          	jal	80000148 <console_putc>
                    chars_printed++;
    800003b8:	2a05                	addw	s4,s4,1
                    break;
    800003ba:	bf99                	j	80000310 <vprintf+0x66>
                    if (!str) str = "(null)";
    800003bc:	00002517          	auipc	a0,0x2
    800003c0:	ccc50513          	add	a0,a0,-820 # 80002088 <_etext+0x88>
    800003c4:	bff1                	j	800003a0 <vprintf+0xf6>
    int chars_printed = 0;
    800003c6:	4a01                	li	s4,0
    800003c8:	bf91                	j	8000031c <vprintf+0x72>

00000000800003ca <printf>:

int printf(const char *fmt, ...) {
    800003ca:	711d                	add	sp,sp,-96
    800003cc:	e822                	sd	s0,16(sp)
    800003ce:	ec06                	sd	ra,24(sp)
    800003d0:	1000                	add	s0,sp,32
    va_list ap;
    va_start(ap, fmt);
    800003d2:	00840313          	add	t1,s0,8
int printf(const char *fmt, ...) {
    800003d6:	e40c                	sd	a1,8(s0)
    800003d8:	e810                	sd	a2,16(s0)
    800003da:	ec14                	sd	a3,24(s0)
    800003dc:	f018                	sd	a4,32(s0)
    800003de:	f41c                	sd	a5,40(s0)
    800003e0:	03043823          	sd	a6,48(s0)
    800003e4:	03143c23          	sd	a7,56(s0)
    int result = vprintf(fmt, ap);
    800003e8:	859a                	mv	a1,t1
    va_start(ap, fmt);
    800003ea:	fe643423          	sd	t1,-24(s0)
    int result = vprintf(fmt, ap);
    800003ee:	ebdff0ef          	jal	800002aa <vprintf>
    va_end(ap);
    return result;
}
    800003f2:	60e2                	ld	ra,24(sp)
    800003f4:	6442                	ld	s0,16(sp)
    800003f6:	6125                	add	sp,sp,96
    800003f8:	8082                	ret

00000000800003fa <clear_screen>:
#include "console.h"

// ANSI转义序列支持
void clear_screen(void) {
    800003fa:	1141                	add	sp,sp,-16
    800003fc:	e422                	sd	s0,8(sp)
    800003fe:	0800                	add	s0,sp,16
    // ESC[2J - 清除整个屏幕
    // ESC[H - 光标移动到左上角
    console_puts("\033[2J\033[H");
}
    80000400:	6422                	ld	s0,8(sp)
    console_puts("\033[2J\033[H");
    80000402:	00002517          	auipc	a0,0x2
    80000406:	d1650513          	add	a0,a0,-746 # 80002118 <_etext+0x118>
}
    8000040a:	0141                	add	sp,sp,16
    console_puts("\033[2J\033[H");
    8000040c:	b3a1                	j	80000154 <console_puts>

000000008000040e <set_cursor_position>:

void set_cursor_position(int row, int col) {
    8000040e:	1101                	add	sp,sp,-32
    80000410:	e822                	sd	s0,16(sp)
    80000412:	ec06                	sd	ra,24(sp)
    80000414:	1000                	add	s0,sp,32
    char buf[16];
    int len = 0;
    
    buf[len++] = '\033';
    80000416:	6799                	lui	a5,0x6
    80000418:	b1b78793          	add	a5,a5,-1253 # 5b1b <_start-0x7fffa4e5>
    8000041c:	fef41023          	sh	a5,-32(s0)
    buf[len++] = '[';
    
    // 行号
    if (row >= 10) {
    80000420:	47a5                	li	a5,9
    80000422:	08a7d763          	bge	a5,a0,800004b0 <set_cursor_position+0xa2>
        buf[len++] = '0' + (row / 10);
    80000426:	47a9                	li	a5,10
    80000428:	02f547bb          	divw	a5,a0,a5
    8000042c:	4715                	li	a4,5
    8000042e:	4691                	li	a3,4
    80000430:	480d                	li	a6,3
    80000432:	0307879b          	addw	a5,a5,48
    80000436:	fef40123          	sb	a5,-30(s0)
    }
    buf[len++] = '0' + (row % 10);
    8000043a:	47a9                	li	a5,10
    8000043c:	02f5653b          	remw	a0,a0,a5
    80000440:	ff080613          	add	a2,a6,-16
    80000444:	9622                	add	a2,a2,s0
    buf[len++] = ';';
    80000446:	16c1                	add	a3,a3,-16 # ffffff0 <_start-0x70000010>
    80000448:	96a2                	add	a3,a3,s0
    
    // 列号
    if (col >= 10) {
    8000044a:	48a5                	li	a7,9
    buf[len++] = '0' + (row % 10);
    8000044c:	0305051b          	addw	a0,a0,48
    80000450:	fea60823          	sb	a0,-16(a2)
    buf[len++] = ';';
    80000454:	03b00613          	li	a2,59
    80000458:	fec68823          	sb	a2,-16(a3)
    if (col >= 10) {
    8000045c:	00b8dd63          	bge	a7,a1,80000476 <set_cursor_position+0x68>
        buf[len++] = '0' + (col / 10);
    80000460:	02f5c7bb          	divw	a5,a1,a5
    80000464:	1741                	add	a4,a4,-16
    80000466:	008706b3          	add	a3,a4,s0
    8000046a:	00380713          	add	a4,a6,3
    8000046e:	0307879b          	addw	a5,a5,48
    80000472:	fef68823          	sb	a5,-16(a3)
    }
    buf[len++] = '0' + (col % 10);
    80000476:	47a9                	li	a5,10
    80000478:	02f5e7bb          	remw	a5,a1,a5
    8000047c:	ff070693          	add	a3,a4,-16
    80000480:	00868633          	add	a2,a3,s0
    buf[len++] = 'H';
    80000484:	0017069b          	addw	a3,a4,1
    80000488:	16c1                	add	a3,a3,-16
    8000048a:	96a2                	add	a3,a3,s0
    
    console_write(buf, len);
    8000048c:	fe040513          	add	a0,s0,-32
    80000490:	0027059b          	addw	a1,a4,2
    buf[len++] = '0' + (col % 10);
    80000494:	0307879b          	addw	a5,a5,48
    80000498:	fef60823          	sb	a5,-16(a2)
    buf[len++] = 'H';
    8000049c:	04800793          	li	a5,72
    800004a0:	fef68823          	sb	a5,-16(a3)
    console_write(buf, len);
    800004a4:	cbdff0ef          	jal	80000160 <console_write>
}
    800004a8:	60e2                	ld	ra,24(sp)
    800004aa:	6442                	ld	s0,16(sp)
    800004ac:	6105                	add	sp,sp,32
    800004ae:	8082                	ret
    800004b0:	4711                	li	a4,4
    800004b2:	468d                	li	a3,3
    buf[len++] = '[';
    800004b4:	4809                	li	a6,2
    800004b6:	b751                	j	8000043a <set_cursor_position+0x2c>

00000000800004b8 <set_foreground_color>:

void set_foreground_color(int color) {
    800004b8:	1101                	add	sp,sp,-32
    800004ba:	e822                	sd	s0,16(sp)
    800004bc:	ec06                	sd	ra,24(sp)
    800004be:	1000                	add	s0,sp,32
    char buf[8];
    int len = 0;
    
    buf[len++] = '\033';
    800004c0:	6719                	lui	a4,0x6
    buf[len++] = '[';
    buf[len++] = '3';
    buf[len++] = '0' + color;
    800004c2:	0305079b          	addw	a5,a0,48
    buf[len++] = '\033';
    800004c6:	b1b70713          	add	a4,a4,-1253 # 5b1b <_start-0x7fffa4e5>
    800004ca:	fee41423          	sh	a4,-24(s0)
    buf[len++] = '0' + color;
    800004ce:	fef405a3          	sb	a5,-21(s0)
    buf[len++] = 'm';
    
    console_write(buf, len);
    800004d2:	fe840513          	add	a0,s0,-24
    buf[len++] = '3';
    800004d6:	03300713          	li	a4,51
    buf[len++] = 'm';
    800004da:	06d00793          	li	a5,109
    console_write(buf, len);
    800004de:	4595                	li	a1,5
    buf[len++] = '3';
    800004e0:	fee40523          	sb	a4,-22(s0)
    buf[len++] = 'm';
    800004e4:	fef40623          	sb	a5,-20(s0)
    console_write(buf, len);
    800004e8:	c79ff0ef          	jal	80000160 <console_write>
}
    800004ec:	60e2                	ld	ra,24(sp)
    800004ee:	6442                	ld	s0,16(sp)
    800004f0:	6105                	add	sp,sp,32
    800004f2:	8082                	ret

00000000800004f4 <set_background_color>:

void set_background_color(int color) {
    800004f4:	1101                	add	sp,sp,-32
    800004f6:	e822                	sd	s0,16(sp)
    800004f8:	ec06                	sd	ra,24(sp)
    800004fa:	1000                	add	s0,sp,32
    char buf[8];
    int len = 0;
    
    buf[len++] = '\033';
    800004fc:	6719                	lui	a4,0x6
    buf[len++] = '[';
    buf[len++] = '4';
    buf[len++] = '0' + color;
    800004fe:	0305079b          	addw	a5,a0,48
    buf[len++] = '\033';
    80000502:	b1b70713          	add	a4,a4,-1253 # 5b1b <_start-0x7fffa4e5>
    80000506:	fee41423          	sh	a4,-24(s0)
    buf[len++] = '0' + color;
    8000050a:	fef405a3          	sb	a5,-21(s0)
    buf[len++] = 'm';
    
    console_write(buf, len);
    8000050e:	fe840513          	add	a0,s0,-24
    buf[len++] = '4';
    80000512:	03400713          	li	a4,52
    buf[len++] = 'm';
    80000516:	06d00793          	li	a5,109
    console_write(buf, len);
    8000051a:	4595                	li	a1,5
    buf[len++] = '4';
    8000051c:	fee40523          	sb	a4,-22(s0)
    buf[len++] = 'm';
    80000520:	fef40623          	sb	a5,-20(s0)
    console_write(buf, len);
    80000524:	c3dff0ef          	jal	80000160 <console_write>
}
    80000528:	60e2                	ld	ra,24(sp)
    8000052a:	6442                	ld	s0,16(sp)
    8000052c:	6105                	add	sp,sp,32
    8000052e:	8082                	ret

0000000080000530 <reset_color>:

void reset_color(void) {
    80000530:	1141                	add	sp,sp,-16
    80000532:	e422                	sd	s0,8(sp)
    80000534:	0800                	add	s0,sp,16
    console_puts("\033[0m");
}
    80000536:	6422                	ld	s0,8(sp)
    console_puts("\033[0m");
    80000538:	00002517          	auipc	a0,0x2
    8000053c:	be850513          	add	a0,a0,-1048 # 80002120 <_etext+0x120>
}
    80000540:	0141                	add	sp,sp,16
    console_puts("\033[0m");
    80000542:	b909                	j	80000154 <console_puts>

0000000080000544 <clear_line>:

void clear_line(void) {
    80000544:	1141                	add	sp,sp,-16
    80000546:	e022                	sd	s0,0(sp)
    80000548:	e406                	sd	ra,8(sp)
    8000054a:	0800                	add	s0,sp,16
    console_puts("\033[2K");  // 清除整行
    8000054c:	00002517          	auipc	a0,0x2
    80000550:	bdc50513          	add	a0,a0,-1060 # 80002128 <_etext+0x128>
    80000554:	c01ff0ef          	jal	80000154 <console_puts>
    console_puts("\033[0G");  // 光标移动到行首
}
    80000558:	6402                	ld	s0,0(sp)
    8000055a:	60a2                	ld	ra,8(sp)
    console_puts("\033[0G");  // 光标移动到行首
    8000055c:	00002517          	auipc	a0,0x2
    80000560:	bd450513          	add	a0,a0,-1068 # 80002130 <_etext+0x130>
}
    80000564:	0141                	add	sp,sp,16
    console_puts("\033[0G");  // 光标移动到行首
    80000566:	b6fd                	j	80000154 <console_puts>

0000000080000568 <memset>:
#include "types.h"
#include "defs.h"

// 设置内存区域为指定值
void* memset(void* dst, int c, uint64 n) {
    80000568:	1141                	add	sp,sp,-16
    8000056a:	e422                	sd	s0,8(sp)
    8000056c:	0800                	add	s0,sp,16
    8000056e:	00a60733          	add	a4,a2,a0
    char* cdst = (char*)dst;
    for (uint64 i = 0; i < n; i++) {
    80000572:	ca09                	beqz	a2,80000584 <memset+0x1c>
    80000574:	0ff5f593          	zext.b	a1,a1
    80000578:	87aa                	mv	a5,a0
        cdst[i] = c;
    8000057a:	00b78023          	sb	a1,0(a5)
    for (uint64 i = 0; i < n; i++) {
    8000057e:	0785                	add	a5,a5,1
    80000580:	fee79de3          	bne	a5,a4,8000057a <memset+0x12>
    }
    return dst;
}
    80000584:	6422                	ld	s0,8(sp)
    80000586:	0141                	add	sp,sp,16
    80000588:	8082                	ret

000000008000058a <memmove>:

// 内存移动（处理重叠区域）
void* memmove(void* dst, const void* src, uint64 n) {
    8000058a:	1141                	add	sp,sp,-16
    8000058c:	e422                	sd	s0,8(sp)
    8000058e:	0800                	add	s0,sp,16
    const char* s = src;
    char* d = dst;
    
    if (s < d && s + n > d) {
    80000590:	02a5f463          	bgeu	a1,a0,800005b8 <memmove+0x2e>
    80000594:	00c587b3          	add	a5,a1,a2
    80000598:	02f57063          	bgeu	a0,a5,800005b8 <memmove+0x2e>
        // 从后向前拷贝，避免重叠问题
        s += n;
        d += n;
    8000059c:	00c50733          	add	a4,a0,a2
        while (n-- > 0) {
    800005a0:	ca09                	beqz	a2,800005b2 <memmove+0x28>
            *--d = *--s;
    800005a2:	fff7c683          	lbu	a3,-1(a5)
    800005a6:	17fd                	add	a5,a5,-1
    800005a8:	177d                	add	a4,a4,-1
    800005aa:	00d70023          	sb	a3,0(a4)
        while (n-- > 0) {
    800005ae:	fef59ae3          	bne	a1,a5,800005a2 <memmove+0x18>
        while (n-- > 0) {
            *d++ = *s++;
        }
    }
    return dst;
}
    800005b2:	6422                	ld	s0,8(sp)
    800005b4:	0141                	add	sp,sp,16
    800005b6:	8082                	ret
        while (n-- > 0) {
    800005b8:	00c586b3          	add	a3,a1,a2
    800005bc:	87aa                	mv	a5,a0
    800005be:	da75                	beqz	a2,800005b2 <memmove+0x28>
            *d++ = *s++;
    800005c0:	0005c703          	lbu	a4,0(a1)
    800005c4:	0585                	add	a1,a1,1
    800005c6:	0785                	add	a5,a5,1
    800005c8:	fee78fa3          	sb	a4,-1(a5)
        while (n-- > 0) {
    800005cc:	fed59ae3          	bne	a1,a3,800005c0 <memmove+0x36>
}
    800005d0:	6422                	ld	s0,8(sp)
    800005d2:	0141                	add	sp,sp,16
    800005d4:	8082                	ret

00000000800005d6 <memcpy>:

// 内存拷贝（不处理重叠区域）
void* memcpy(void* dst, const void* src, uint64 n) {
    800005d6:	1141                	add	sp,sp,-16
    800005d8:	e422                	sd	s0,8(sp)
    800005da:	0800                	add	s0,sp,16
    return memmove(dst, src, n); // 简单实现，使用memmove
    800005dc:	6422                	ld	s0,8(sp)
    800005de:	0141                	add	sp,sp,16
    return memmove(dst, src, n); // 简单实现，使用memmove
    800005e0:	b76d                	j	8000058a <memmove>

00000000800005e2 <print_int>:
    
    return i;
}

// 输出数字到控制台
void print_int(int32 num) {
    800005e2:	7179                	add	sp,sp,-48
    800005e4:	f022                	sd	s0,32(sp)
    800005e6:	f406                	sd	ra,40(sp)
    800005e8:	1800                	add	s0,sp,48
    if (num == -2147483648) {
    800005ea:	800007b7          	lui	a5,0x80000
    800005ee:	0af50063          	beq	a0,a5,8000068e <print_int+0xac>
    800005f2:	872a                	mv	a4,a0
    if (num < 0) {
    800005f4:	02054063          	bltz	a0,80000614 <print_int+0x32>
    if (num == 0) {
    800005f8:	e561                	bnez	a0,800006c0 <print_int+0xde>
        buf[i++] = '0';
    800005fa:	03000793          	li	a5,48
    800005fe:	fcf40823          	sb	a5,-48(s0)
    80000602:	4585                	li	a1,1
    80000604:	fd040513          	add	a0,s0,-48
    char buf[32];
    int len = itoa_dec(num, buf);
    console_write(buf, len);
    80000608:	b59ff0ef          	jal	80000160 <console_write>
}
    8000060c:	70a2                	ld	ra,40(sp)
    8000060e:	7402                	ld	s0,32(sp)
    80000610:	6145                	add	sp,sp,48
    80000612:	8082                	ret
        num = -num;
    80000614:	40a0073b          	negw	a4,a0
        is_negative = 1;
    80000618:	4e05                	li	t3,1
    8000061a:	fd040513          	add	a0,s0,-48
    8000061e:	87aa                	mv	a5,a0
    int is_negative = 0;
    80000620:	882a                	mv	a6,a0
    int i = 0;
    80000622:	4581                	li	a1,0
            buf[i++] = '0' + (num % 10);
    80000624:	48a9                	li	a7,10
    80000626:	031766bb          	remw	a3,a4,a7
        while (num > 0) {
    8000062a:	0805                	add	a6,a6,1
            buf[i++] = '0' + (num % 10);
    8000062c:	0015831b          	addw	t1,a1,1
    80000630:	862e                	mv	a2,a1
    80000632:	0003059b          	sext.w	a1,t1
            num /= 10;
    80000636:	0317473b          	divw	a4,a4,a7
            buf[i++] = '0' + (num % 10);
    8000063a:	0306869b          	addw	a3,a3,48
    8000063e:	fed80fa3          	sb	a3,-1(a6)
        while (num > 0) {
    80000642:	f375                	bnez	a4,80000626 <print_int+0x44>
    if (is_negative) {
    80000644:	080e0063          	beqz	t3,800006c4 <print_int+0xe2>
        buf[i++] = '-';
    80000648:	ff058713          	add	a4,a1,-16
    8000064c:	2609                	addw	a2,a2,2
    8000064e:	9722                	add	a4,a4,s0
    80000650:	02d00693          	li	a3,45
    80000654:	0006059b          	sext.w	a1,a2
    80000658:	fed70023          	sb	a3,-32(a4)
    for (int j = 0; j < i / 2; j++) {
    8000065c:	4016561b          	sraw	a2,a2,0x1
    80000660:	fff58713          	add	a4,a1,-1
    80000664:	972a                	add	a4,a4,a0
    80000666:	00c50833          	add	a6,a0,a2
        buf[j] = buf[i - j - 1];
    8000066a:	00074603          	lbu	a2,0(a4)
        char temp = buf[j];
    8000066e:	0007c683          	lbu	a3,0(a5) # ffffffff80000000 <kernel_pagetable+0xfffffffeffffc000>
    for (int j = 0; j < i / 2; j++) {
    80000672:	0785                	add	a5,a5,1
    80000674:	177d                	add	a4,a4,-1
        buf[j] = buf[i - j - 1];
    80000676:	fec78fa3          	sb	a2,-1(a5)
        buf[i - j - 1] = temp;
    8000067a:	00d700a3          	sb	a3,1(a4)
    for (int j = 0; j < i / 2; j++) {
    8000067e:	ff0796e3          	bne	a5,a6,8000066a <print_int+0x88>
    console_write(buf, len);
    80000682:	adfff0ef          	jal	80000160 <console_write>
}
    80000686:	70a2                	ld	ra,40(sp)
    80000688:	7402                	ld	s0,32(sp)
    8000068a:	6145                	add	sp,sp,48
    8000068c:	8082                	ret
    8000068e:	fd040513          	add	a0,s0,-48
    80000692:	00002697          	auipc	a3,0x2
    80000696:	aa768693          	add	a3,a3,-1369 # 80002139 <_etext+0x139>
    if (num == -2147483648) {
    8000069a:	87aa                	mv	a5,a0
        while (min_str[j] != '\0') {
    8000069c:	02d00713          	li	a4,45
            buf[i++] = min_str[j++];
    800006a0:	00e78023          	sb	a4,0(a5)
        while (min_str[j] != '\0') {
    800006a4:	0006c703          	lbu	a4,0(a3)
    800006a8:	85be                	mv	a1,a5
    800006aa:	0685                	add	a3,a3,1
    800006ac:	0785                	add	a5,a5,1
    800006ae:	fb6d                	bnez	a4,800006a0 <print_int+0xbe>
            buf[i++] = min_str[j++];
    800006b0:	9d89                	subw	a1,a1,a0
    800006b2:	2585                	addw	a1,a1,1
    console_write(buf, len);
    800006b4:	aadff0ef          	jal	80000160 <console_write>
}
    800006b8:	70a2                	ld	ra,40(sp)
    800006ba:	7402                	ld	s0,32(sp)
    800006bc:	6145                	add	sp,sp,48
    800006be:	8082                	ret
    int is_negative = 0;
    800006c0:	4e01                	li	t3,0
    800006c2:	bfa1                	j	8000061a <print_int+0x38>
    for (int j = 0; j < i / 2; j++) {
    800006c4:	4013561b          	sraw	a2,t1,0x1
    800006c8:	fe41                	bnez	a2,80000660 <print_int+0x7e>
            buf[i++] = '0' + (num % 10);
    800006ca:	4585                	li	a1,1
    800006cc:	bf35                	j	80000608 <print_int+0x26>

00000000800006ce <print_uint>:

void print_uint(uint32 num, uint32 base, int uppercase) {
    800006ce:	7179                	add	sp,sp,-48
    800006d0:	f022                	sd	s0,32(sp)
    800006d2:	f406                	sd	ra,40(sp)
    800006d4:	1800                	add	s0,sp,48
    800006d6:	86aa                	mv	a3,a0
    const char *digits = uppercase ? hex_digits_upper : hex_digits_lower;
    800006d8:	00002317          	auipc	t1,0x2
    800006dc:	a7030313          	add	t1,t1,-1424 # 80002148 <_etext+0x148>
    800006e0:	e609                	bnez	a2,800006ea <print_uint+0x1c>
    800006e2:	00002317          	auipc	t1,0x2
    800006e6:	a7e30313          	add	t1,t1,-1410 # 80002160 <_etext+0x160>
    if (num == 0) {
    800006ea:	ee91                	bnez	a3,80000706 <print_uint+0x38>
        buf[i++] = '0';
    800006ec:	03000793          	li	a5,48
    800006f0:	fcf40823          	sb	a5,-48(s0)
    800006f4:	4585                	li	a1,1
    800006f6:	fd040513          	add	a0,s0,-48
    char buf[32];
    int len = utoa_base(num, base, uppercase, buf);
    console_write(buf, len);
    800006fa:	a67ff0ef          	jal	80000160 <console_write>
}
    800006fe:	70a2                	ld	ra,40(sp)
    80000700:	7402                	ld	s0,32(sp)
    80000702:	6145                	add	sp,sp,48
    80000704:	8082                	ret
    80000706:	fd040513          	add	a0,s0,-48
    8000070a:	87aa                	mv	a5,a0
    if (num == 0) {
    8000070c:	862a                	mv	a2,a0
            buf[i++] = digits[num % base];
    8000070e:	02b6f73b          	remuw	a4,a3,a1
    80000712:	8832                	mv	a6,a2
        while (num > 0) {
    80000714:	0605                	add	a2,a2,1
    80000716:	0006889b          	sext.w	a7,a3
            buf[i++] = digits[num % base];
    8000071a:	1702                	sll	a4,a4,0x20
    8000071c:	9301                	srl	a4,a4,0x20
    8000071e:	971a                	add	a4,a4,t1
    80000720:	00074703          	lbu	a4,0(a4)
            num /= base;
    80000724:	02b6d6bb          	divuw	a3,a3,a1
            buf[i++] = digits[num % base];
    80000728:	fee60fa3          	sb	a4,-1(a2)
        while (num > 0) {
    8000072c:	feb8f1e3          	bgeu	a7,a1,8000070e <print_uint+0x40>
            buf[i++] = digits[num % base];
    80000730:	40a805bb          	subw	a1,a6,a0
    80000734:	2585                	addw	a1,a1,1
    for (int j = 0; j < i / 2; j++) {
    80000736:	4015d81b          	sraw	a6,a1,0x1
    8000073a:	fc0800e3          	beqz	a6,800006fa <print_uint+0x2c>
    8000073e:	fff58713          	add	a4,a1,-1
    80000742:	972a                	add	a4,a4,a0
    80000744:	982a                	add	a6,a6,a0
        buf[j] = buf[i - j - 1];
    80000746:	00074603          	lbu	a2,0(a4)
        char temp = buf[j];
    8000074a:	0007c683          	lbu	a3,0(a5)
    for (int j = 0; j < i / 2; j++) {
    8000074e:	0785                	add	a5,a5,1
    80000750:	177d                	add	a4,a4,-1
        buf[j] = buf[i - j - 1];
    80000752:	fec78fa3          	sb	a2,-1(a5)
        buf[i - j - 1] = temp;
    80000756:	00d700a3          	sb	a3,1(a4)
    for (int j = 0; j < i / 2; j++) {
    8000075a:	ff0796e3          	bne	a5,a6,80000746 <print_uint+0x78>
    console_write(buf, len);
    8000075e:	a03ff0ef          	jal	80000160 <console_write>
}
    80000762:	70a2                	ld	ra,40(sp)
    80000764:	7402                	ld	s0,32(sp)
    80000766:	6145                	add	sp,sp,48
    80000768:	8082                	ret

000000008000076a <print_pointer>:

void print_pointer(uintptr_t ptr) {
    8000076a:	1101                	add	sp,sp,-32
    8000076c:	e822                	sd	s0,16(sp)
    8000076e:	e426                	sd	s1,8(sp)
    80000770:	ec06                	sd	ra,24(sp)
    80000772:	1000                	add	s0,sp,32
    80000774:	84aa                	mv	s1,a0
    console_puts("0x");
    80000776:	00002517          	auipc	a0,0x2
    8000077a:	a0250513          	add	a0,a0,-1534 # 80002178 <_etext+0x178>
    8000077e:	9d7ff0ef          	jal	80000154 <console_puts>
    print_uint(ptr, 16, 0);
}
    80000782:	6442                	ld	s0,16(sp)
    80000784:	60e2                	ld	ra,24(sp)
    print_uint(ptr, 16, 0);
    80000786:	8526                	mv	a0,s1
}
    80000788:	64a2                	ld	s1,8(sp)
    print_uint(ptr, 16, 0);
    8000078a:	4601                	li	a2,0
    8000078c:	45c1                	li	a1,16
}
    8000078e:	6105                	add	sp,sp,32
    print_uint(ptr, 16, 0);
    80000790:	bf3d                	j	800006ce <print_uint>

0000000080000792 <create_pagetable>:
#include "memlayout.h"

static void map_region(pagetable_t pt, uint64 va, uint64 pa, uint64 size, int perm);
// 创建空页表
pagetable_t create_pagetable(void)
{
    80000792:	1101                	add	sp,sp,-32
    80000794:	e822                	sd	s0,16(sp)
    80000796:	e426                	sd	s1,8(sp)
    80000798:	ec06                	sd	ra,24(sp)
    8000079a:	1000                	add	s0,sp,32
    pagetable_t pt = (pagetable_t)alloc_page();
    8000079c:	7a6000ef          	jal	80000f42 <alloc_page>
    800007a0:	84aa                	mv	s1,a0
    if(pt) {
    800007a2:	c509                	beqz	a0,800007ac <create_pagetable+0x1a>
        memset(pt, 0, PAGE_SIZE);
    800007a4:	6605                	lui	a2,0x1
    800007a6:	4581                	li	a1,0
    800007a8:	dc1ff0ef          	jal	80000568 <memset>
    }
    return pt;
}
    800007ac:	60e2                	ld	ra,24(sp)
    800007ae:	6442                	ld	s0,16(sp)
    800007b0:	8526                	mv	a0,s1
    800007b2:	64a2                	ld	s1,8(sp)
    800007b4:	6105                	add	sp,sp,32
    800007b6:	8082                	ret

00000000800007b8 <free_pagetable>:

// 释放页表（递归释放）
void free_pagetable(pagetable_t pt, int level)
{
    800007b8:	7139                	add	sp,sp,-64
    800007ba:	f822                	sd	s0,48(sp)
    800007bc:	fc06                	sd	ra,56(sp)
    800007be:	f426                	sd	s1,40(sp)
    800007c0:	f04a                	sd	s2,32(sp)
    800007c2:	ec4e                	sd	s3,24(sp)
    800007c4:	e852                	sd	s4,16(sp)
    800007c6:	e456                	sd	s5,8(sp)
    800007c8:	0080                	add	s0,sp,64
    if((uint64)pt % PAGE_SIZE != 0 || pt == 0)
    800007ca:	03451793          	sll	a5,a0,0x34
    800007ce:	eba1                	bnez	a5,8000081e <free_pagetable+0x66>
    800007d0:	8a2a                	mv	s4,a0
    800007d2:	c531                	beqz	a0,8000081e <free_pagetable+0x66>
        panic("free_pagetable: invalid page table");
    
    // 递归释放下级页表
    if(level > 0) {
    800007d4:	02b05a63          	blez	a1,80000808 <free_pagetable+0x50>
    800007d8:	6905                	lui	s2,0x1
    800007da:	84aa                	mv	s1,a0
    800007dc:	992a                	add	s2,s2,a0
        for(int i = 0; i < 512; i++) {
            pte_t pte = pt[i];
            if(pte & PTE_V && (pte & (PTE_R|PTE_W|PTE_X)) == 0) {
    800007de:	4985                	li	s3,1
                uint64 child = PTE2PA(pte);
                free_pagetable((pagetable_t)child, level - 1);
    800007e0:	fff58a9b          	addw	s5,a1,-1
    800007e4:	a021                	j	800007ec <free_pagetable+0x34>
        for(int i = 0; i < 512; i++) {
    800007e6:	04a1                	add	s1,s1,8
    800007e8:	03248063          	beq	s1,s2,80000808 <free_pagetable+0x50>
            pte_t pte = pt[i];
    800007ec:	609c                	ld	a5,0(s1)
            if(pte & PTE_V && (pte & (PTE_R|PTE_W|PTE_X)) == 0) {
    800007ee:	00f7f713          	and	a4,a5,15
    800007f2:	ff371ae3          	bne	a4,s3,800007e6 <free_pagetable+0x2e>
                uint64 child = PTE2PA(pte);
    800007f6:	83a9                	srl	a5,a5,0xa
                free_pagetable((pagetable_t)child, level - 1);
    800007f8:	85d6                	mv	a1,s5
    800007fa:	00c79513          	sll	a0,a5,0xc
        for(int i = 0; i < 512; i++) {
    800007fe:	04a1                	add	s1,s1,8
                free_pagetable((pagetable_t)child, level - 1);
    80000800:	fb9ff0ef          	jal	800007b8 <free_pagetable>
        for(int i = 0; i < 512; i++) {
    80000804:	ff2494e3          	bne	s1,s2,800007ec <free_pagetable+0x34>
            }
        }
    }
    
    free_page(pt);
}
    80000808:	7442                	ld	s0,48(sp)
    8000080a:	70e2                	ld	ra,56(sp)
    8000080c:	74a2                	ld	s1,40(sp)
    8000080e:	7902                	ld	s2,32(sp)
    80000810:	69e2                	ld	s3,24(sp)
    80000812:	6aa2                	ld	s5,8(sp)
    free_page(pt);
    80000814:	8552                	mv	a0,s4
}
    80000816:	6a42                	ld	s4,16(sp)
    80000818:	6121                	add	sp,sp,64
    free_page(pt);
    8000081a:	7a80006f          	j	80000fc2 <free_page>
        panic("free_pagetable: invalid page table");
    8000081e:	00002517          	auipc	a0,0x2
    80000822:	96250513          	add	a0,a0,-1694 # 80002180 <_etext+0x180>
    80000826:	a53ff0ef          	jal	80000278 <panic>

000000008000082a <walk_lookup>:
}

// 页表遍历（必要时创建）
pte_t* walk_create(pagetable_t pt, uint64 va, int alloc)
{
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    8000082a:	57fd                	li	a5,-1
    8000082c:	83e9                	srl	a5,a5,0x1a
    8000082e:	872a                	mv	a4,a0
    80000830:	46f9                	li	a3,30
    80000832:	02b7e763          	bltu	a5,a1,80000860 <walk_lookup+0x36>
    
    pagetable_t cur = pt;
    pte_t *pte;
    
    for(int level = 2; level >= 0; level--) {
        pte = &cur[PX(level, va)];
    80000836:	00d5d7b3          	srl	a5,a1,a3
    8000083a:	1ff7f793          	and	a5,a5,511
    8000083e:	078e                	sll	a5,a5,0x3
    80000840:	00f70533          	add	a0,a4,a5
        if(*pte & PTE_V) {
    80000844:	611c                	ld	a5,0(a0)
    80000846:	0017f713          	and	a4,a5,1
    8000084a:	cb09                	beqz	a4,8000085c <walk_lookup+0x32>
            // 有效PTE，进入下一级
            cur = (pagetable_t)PTE2PA(*pte);
    8000084c:	83a9                	srl	a5,a5,0xa
    for(int level = 2; level >= 0; level--) {
    8000084e:	36dd                	addw	a3,a3,-9
    80000850:	460d                	li	a2,3
            cur = (pagetable_t)PTE2PA(*pte);
    80000852:	00c79713          	sll	a4,a5,0xc
    for(int level = 2; level >= 0; level--) {
    80000856:	fec690e3          	bne	a3,a2,80000836 <walk_lookup+0xc>
    8000085a:	8082                	ret
        } else {
            // PTE无效
            if(!alloc) return 0;
    8000085c:	4501                	li	a0,0
}
    8000085e:	8082                	ret
{
    80000860:	1141                	add	sp,sp,-16
    80000862:	e022                	sd	s0,0(sp)
    80000864:	e406                	sd	ra,8(sp)
    80000866:	0800                	add	s0,sp,16
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    80000868:	00002517          	auipc	a0,0x2
    8000086c:	94050513          	add	a0,a0,-1728 # 800021a8 <_etext+0x1a8>
    80000870:	a09ff0ef          	jal	80000278 <panic>

0000000080000874 <walk_create>:
{
    80000874:	7139                	add	sp,sp,-64
    80000876:	f822                	sd	s0,48(sp)
    80000878:	fc06                	sd	ra,56(sp)
    8000087a:	f426                	sd	s1,40(sp)
    8000087c:	f04a                	sd	s2,32(sp)
    8000087e:	ec4e                	sd	s3,24(sp)
    80000880:	e852                	sd	s4,16(sp)
    80000882:	e456                	sd	s5,8(sp)
    80000884:	e05a                	sd	s6,0(sp)
    80000886:	0080                	add	s0,sp,64
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    80000888:	57fd                	li	a5,-1
    8000088a:	83e9                	srl	a5,a5,0x1a
    8000088c:	06b7e663          	bltu	a5,a1,800008f8 <walk_create+0x84>
    80000890:	89ae                	mv	s3,a1
    80000892:	892a                	mv	s2,a0
    80000894:	8a32                	mv	s4,a2
    80000896:	4b79                	li	s6,30
    80000898:	4a8d                	li	s5,3
        pte = &cur[PX(level, va)];
    8000089a:	0169d4b3          	srl	s1,s3,s6
    8000089e:	1ff4f493          	and	s1,s1,511
    800008a2:	048e                	sll	s1,s1,0x3
    800008a4:	94ca                	add	s1,s1,s2
        if(*pte & PTE_V) {
    800008a6:	0004b903          	ld	s2,0(s1)
    800008aa:	00197793          	and	a5,s2,1
    800008ae:	c395                	beqz	a5,800008d2 <walk_create+0x5e>
            cur = (pagetable_t)PTE2PA(*pte);
    800008b0:	00a95913          	srl	s2,s2,0xa
    800008b4:	0932                	sll	s2,s2,0xc
    for(int level = 2; level >= 0; level--) {
    800008b6:	3b5d                	addw	s6,s6,-9
    800008b8:	ff5b11e3          	bne	s6,s5,8000089a <walk_create+0x26>
            *pte = PA2PTE((uint64)new_pt) | PTE_V;
            cur = new_pt;
        }
    }
    return pte;
}
    800008bc:	70e2                	ld	ra,56(sp)
    800008be:	7442                	ld	s0,48(sp)
    800008c0:	7902                	ld	s2,32(sp)
    800008c2:	69e2                	ld	s3,24(sp)
    800008c4:	6a42                	ld	s4,16(sp)
    800008c6:	6aa2                	ld	s5,8(sp)
    800008c8:	6b02                	ld	s6,0(sp)
    800008ca:	8526                	mv	a0,s1
    800008cc:	74a2                	ld	s1,40(sp)
    800008ce:	6121                	add	sp,sp,64
    800008d0:	8082                	ret
            if(!alloc) return 0;
    800008d2:	020a0163          	beqz	s4,800008f4 <walk_create+0x80>
            pagetable_t new_pt = (pagetable_t)alloc_page();
    800008d6:	66c000ef          	jal	80000f42 <alloc_page>
    800008da:	892a                	mv	s2,a0
            if(new_pt == 0) return 0;
    800008dc:	cd01                	beqz	a0,800008f4 <walk_create+0x80>
            memset(new_pt, 0, PAGE_SIZE);
    800008de:	6605                	lui	a2,0x1
    800008e0:	4581                	li	a1,0
    800008e2:	c87ff0ef          	jal	80000568 <memset>
            *pte = PA2PTE((uint64)new_pt) | PTE_V;
    800008e6:	00c95793          	srl	a5,s2,0xc
    800008ea:	07aa                	sll	a5,a5,0xa
    800008ec:	0017e793          	or	a5,a5,1
    800008f0:	e09c                	sd	a5,0(s1)
            cur = new_pt;
    800008f2:	b7d1                	j	800008b6 <walk_create+0x42>
            if(!alloc) return 0;
    800008f4:	4481                	li	s1,0
    800008f6:	b7d9                	j	800008bc <walk_create+0x48>
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    800008f8:	00002517          	auipc	a0,0x2
    800008fc:	8b050513          	add	a0,a0,-1872 # 800021a8 <_etext+0x1a8>
    80000900:	979ff0ef          	jal	80000278 <panic>

0000000080000904 <map_region>:
    cprintf("kvminit: kernel page table created\n");
}

// 映射连续内存区域
void map_region(pagetable_t pt, uint64 va, uint64 pa, uint64 size, int perm)
{
    80000904:	715d                	add	sp,sp,-80
    80000906:	f84a                	sd	s2,48(sp)
    if(size % PAGE_SIZE != 0)
    80000908:	6905                	lui	s2,0x1
{
    8000090a:	e0a2                	sd	s0,64(sp)
    8000090c:	e486                	sd	ra,72(sp)
    8000090e:	fc26                	sd	s1,56(sp)
    80000910:	f44e                	sd	s3,40(sp)
    80000912:	f052                	sd	s4,32(sp)
    80000914:	ec56                	sd	s5,24(sp)
    80000916:	e85a                	sd	s6,16(sp)
    80000918:	e45e                	sd	s7,8(sp)
    8000091a:	e062                	sd	s8,0(sp)
    8000091c:	0880                	add	s0,sp,80
    if(size % PAGE_SIZE != 0)
    8000091e:	197d                	add	s2,s2,-1 # fff <_start-0x7ffff001>
    80000920:	0126f7b3          	and	a5,a3,s2
    80000924:	ebd1                	bnez	a5,800009b8 <map_region+0xb4>
    80000926:	84b6                	mv	s1,a3
        panic("map_region: size not page aligned");
    
    for(uint64 i = 0; i < size; i += PAGE_SIZE) {
    80000928:	cab1                	beqz	a3,8000097c <map_region+0x78>
    if(va % PAGE_SIZE != 0 || pa % PAGE_SIZE != 0)
    8000092a:	00c5e7b3          	or	a5,a1,a2
    8000092e:	0127f7b3          	and	a5,a5,s2
    80000932:	8b2e                	mv	s6,a1
    80000934:	8bb2                	mv	s7,a2
    80000936:	e7ad                	bnez	a5,800009a0 <map_region+0x9c>
    for(uint64 i = 0; i < size; i += PAGE_SIZE) {
    80000938:	6c05                	lui	s8,0x1
    8000093a:	89aa                	mv	s3,a0
    8000093c:	8a3a                	mv	s4,a4
    8000093e:	40bc0ab3          	sub	s5,s8,a1
    80000942:	a801                	j	80000952 <map_region+0x4e>
        if(map_page(pt, va + i, pa + i, perm) < 0) {
    80000944:	9b62                	add	s6,s6,s8
    80000946:	9be2                	add	s7,s7,s8
    if(va % PAGE_SIZE != 0 || pa % PAGE_SIZE != 0)
    80000948:	017b67b3          	or	a5,s6,s7
    8000094c:	0127f7b3          	and	a5,a5,s2
    80000950:	eba1                	bnez	a5,800009a0 <map_region+0x9c>
    pte_t *pte = walk_create(pt, va, 1);
    80000952:	4605                	li	a2,1
    80000954:	85da                	mv	a1,s6
    80000956:	854e                	mv	a0,s3
    80000958:	f1dff0ef          	jal	80000874 <walk_create>
    if(pte == 0) return -1;
    8000095c:	cd05                	beqz	a0,80000994 <map_region+0x90>
    if(*pte & PTE_V) {
    8000095e:	611c                	ld	a5,0(a0)
    80000960:	8b85                	and	a5,a5,1
    80000962:	e7a9                	bnez	a5,800009ac <map_region+0xa8>
    *pte = PA2PTE(pa) | perm | PTE_V;
    80000964:	00cbd793          	srl	a5,s7,0xc
    80000968:	07aa                	sll	a5,a5,0xa
    8000096a:	0147e7b3          	or	a5,a5,s4
    8000096e:	0017e793          	or	a5,a5,1
    80000972:	e11c                	sd	a5,0(a0)
    for(uint64 i = 0; i < size; i += PAGE_SIZE) {
    80000974:	016a87b3          	add	a5,s5,s6
    80000978:	fc97e6e3          	bltu	a5,s1,80000944 <map_region+0x40>
            panic("map_region: failed to map page");
        }
    }
}
    8000097c:	60a6                	ld	ra,72(sp)
    8000097e:	6406                	ld	s0,64(sp)
    80000980:	74e2                	ld	s1,56(sp)
    80000982:	7942                	ld	s2,48(sp)
    80000984:	79a2                	ld	s3,40(sp)
    80000986:	7a02                	ld	s4,32(sp)
    80000988:	6ae2                	ld	s5,24(sp)
    8000098a:	6b42                	ld	s6,16(sp)
    8000098c:	6ba2                	ld	s7,8(sp)
    8000098e:	6c02                	ld	s8,0(sp)
    80000990:	6161                	add	sp,sp,80
    80000992:	8082                	ret
            panic("map_region: failed to map page");
    80000994:	00002517          	auipc	a0,0x2
    80000998:	88450513          	add	a0,a0,-1916 # 80002218 <_etext+0x218>
    8000099c:	8ddff0ef          	jal	80000278 <panic>
        panic("map_page: unaligned address");
    800009a0:	00002517          	auipc	a0,0x2
    800009a4:	85850513          	add	a0,a0,-1960 # 800021f8 <_etext+0x1f8>
    800009a8:	8d1ff0ef          	jal	80000278 <panic>
        panic("map_page: remapping existing page");
    800009ac:	00002517          	auipc	a0,0x2
    800009b0:	88c50513          	add	a0,a0,-1908 # 80002238 <_etext+0x238>
    800009b4:	8c5ff0ef          	jal	80000278 <panic>
        panic("map_region: size not page aligned");
    800009b8:	00002517          	auipc	a0,0x2
    800009bc:	81850513          	add	a0,a0,-2024 # 800021d0 <_etext+0x1d0>
    800009c0:	8b9ff0ef          	jal	80000278 <panic>

00000000800009c4 <map_page>:
{
    800009c4:	1101                	add	sp,sp,-32
    800009c6:	e822                	sd	s0,16(sp)
    800009c8:	ec06                	sd	ra,24(sp)
    800009ca:	e426                	sd	s1,8(sp)
    800009cc:	e04a                	sd	s2,0(sp)
    800009ce:	1000                	add	s0,sp,32
    if(va % PAGE_SIZE != 0 || pa % PAGE_SIZE != 0)
    800009d0:	00c5e7b3          	or	a5,a1,a2
    800009d4:	17d2                	sll	a5,a5,0x34
    800009d6:	eb95                	bnez	a5,80000a0a <map_page+0x46>
    800009d8:	84b2                	mv	s1,a2
    pte_t *pte = walk_create(pt, va, 1);
    800009da:	4605                	li	a2,1
    800009dc:	8936                	mv	s2,a3
    800009de:	e97ff0ef          	jal	80000874 <walk_create>
    if(pte == 0) return -1;
    800009e2:	c115                	beqz	a0,80000a06 <map_page+0x42>
    if(*pte & PTE_V) {
    800009e4:	611c                	ld	a5,0(a0)
    800009e6:	8b85                	and	a5,a5,1
    800009e8:	e79d                	bnez	a5,80000a16 <map_page+0x52>
    *pte = PA2PTE(pa) | perm | PTE_V;
    800009ea:	80b1                	srl	s1,s1,0xc
    800009ec:	04aa                	sll	s1,s1,0xa
    800009ee:	0124e4b3          	or	s1,s1,s2
    800009f2:	0014e493          	or	s1,s1,1
    800009f6:	e104                	sd	s1,0(a0)
    return 0;
    800009f8:	4501                	li	a0,0
}
    800009fa:	60e2                	ld	ra,24(sp)
    800009fc:	6442                	ld	s0,16(sp)
    800009fe:	64a2                	ld	s1,8(sp)
    80000a00:	6902                	ld	s2,0(sp)
    80000a02:	6105                	add	sp,sp,32
    80000a04:	8082                	ret
    if(pte == 0) return -1;
    80000a06:	557d                	li	a0,-1
    80000a08:	bfcd                	j	800009fa <map_page+0x36>
        panic("map_page: unaligned address");
    80000a0a:	00001517          	auipc	a0,0x1
    80000a0e:	7ee50513          	add	a0,a0,2030 # 800021f8 <_etext+0x1f8>
    80000a12:	867ff0ef          	jal	80000278 <panic>
        panic("map_page: remapping existing page");
    80000a16:	00002517          	auipc	a0,0x2
    80000a1a:	82250513          	add	a0,a0,-2014 # 80002238 <_etext+0x238>
    80000a1e:	85bff0ef          	jal	80000278 <panic>

0000000080000a22 <unmap_page>:
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    80000a22:	57fd                	li	a5,-1
    80000a24:	83e9                	srl	a5,a5,0x1a
    80000a26:	4779                	li	a4,30
    80000a28:	02b7ea63          	bltu	a5,a1,80000a5c <unmap_page+0x3a>
        pte = &cur[PX(level, va)];
    80000a2c:	00e5d7b3          	srl	a5,a1,a4
    80000a30:	1ff7f793          	and	a5,a5,511
    80000a34:	078e                	sll	a5,a5,0x3
    80000a36:	97aa                	add	a5,a5,a0
        if(*pte & PTE_V) {
    80000a38:	6388                	ld	a0,0(a5)
    80000a3a:	00157693          	and	a3,a0,1
    80000a3e:	ce89                	beqz	a3,80000a58 <unmap_page+0x36>
            cur = (pagetable_t)PTE2PA(*pte);
    80000a40:	8129                	srl	a0,a0,0xa
    for(int level = 2; level >= 0; level--) {
    80000a42:	375d                	addw	a4,a4,-9
    80000a44:	468d                	li	a3,3
            cur = (pagetable_t)PTE2PA(*pte);
    80000a46:	0532                	sll	a0,a0,0xc
    for(int level = 2; level >= 0; level--) {
    80000a48:	fed712e3          	bne	a4,a3,80000a2c <unmap_page+0xa>
    *pte = 0; // 清除PTE
    80000a4c:	0007b023          	sd	zero,0(a5)
    asm volatile("sfence.vma zero, %0" : : "r" (va));
    80000a50:	12b00073          	sfence.vma	zero,a1
    return 0;
    80000a54:	4501                	li	a0,0
    80000a56:	8082                	ret
        return -1; // 未映射
    80000a58:	557d                	li	a0,-1
}
    80000a5a:	8082                	ret
{
    80000a5c:	1141                	add	sp,sp,-16
    80000a5e:	e022                	sd	s0,0(sp)
    80000a60:	e406                	sd	ra,8(sp)
    80000a62:	0800                	add	s0,sp,16
    if(va >= MAXVA) panic("walk_create: virtual address too high");
    80000a64:	00001517          	auipc	a0,0x1
    80000a68:	74450513          	add	a0,a0,1860 # 800021a8 <_etext+0x1a8>
    80000a6c:	80dff0ef          	jal	80000278 <panic>

0000000080000a70 <dump_pagetable>:
{
    80000a70:	711d                	add	sp,sp,-96
    80000a72:	e8a2                	sd	s0,80(sp)
    80000a74:	fc4e                	sd	s3,56(sp)
    80000a76:	f852                	sd	s4,48(sp)
    80000a78:	f456                	sd	s5,40(sp)
    80000a7a:	f05a                	sd	s6,32(sp)
    80000a7c:	ec5e                	sd	s7,24(sp)
    80000a7e:	e862                	sd	s8,16(sp)
    80000a80:	e466                	sd	s9,8(sp)
    80000a82:	ec86                	sd	ra,88(sp)
    80000a84:	e4a6                	sd	s1,72(sp)
    80000a86:	e0ca                	sd	s2,64(sp)
    80000a88:	1080                	add	s0,sp,96
            cprintf("%s[%d]: PTE %p -> PA %p perm: ", 
    80000a8a:	00359793          	sll	a5,a1,0x3
            for(int l = 0; l < 2 - level; l++) cprintf("  ");
    80000a8e:	4a89                	li	s5,2
            cprintf("%s[%d]: PTE %p -> PA %p perm: ", 
    80000a90:	00002c17          	auipc	s8,0x2
    80000a94:	888c0c13          	add	s8,s8,-1912 # 80002318 <level_names.0>
{
    80000a98:	8bae                	mv	s7,a1
    80000a9a:	8a2a                	mv	s4,a0
    for(int i = 0; i < 512; i++) {
    80000a9c:	4981                	li	s3,0
            for(int l = 0; l < 2 - level; l++) cprintf("  ");
    80000a9e:	40ba8abb          	subw	s5,s5,a1
            cprintf("%s[%d]: PTE %p -> PA %p perm: ", 
    80000aa2:	9c3e                	add	s8,s8,a5
    80000aa4:	00001c97          	auipc	s9,0x1
    80000aa8:	7c4c8c93          	add	s9,s9,1988 # 80002268 <_etext+0x268>
            for(int l = 0; l < 2 - level; l++) cprintf("  ");
    80000aac:	00001b17          	auipc	s6,0x1
    80000ab0:	7b4b0b13          	add	s6,s6,1972 # 80002260 <_etext+0x260>
    80000ab4:	a039                	j	80000ac2 <dump_pagetable+0x52>
    for(int i = 0; i < 512; i++) {
    80000ab6:	2985                	addw	s3,s3,1
    80000ab8:	20000793          	li	a5,512
    80000abc:	0a21                	add	s4,s4,8
    80000abe:	08f98163          	beq	s3,a5,80000b40 <dump_pagetable+0xd0>
        pte_t pte = pt[i];
    80000ac2:	000a3903          	ld	s2,0(s4)
        if(pte & PTE_V) {
    80000ac6:	00197793          	and	a5,s2,1
    80000aca:	d7f5                	beqz	a5,80000ab6 <dump_pagetable+0x46>
            for(int l = 0; l < 2 - level; l++) cprintf("  ");
    80000acc:	01505963          	blez	s5,80000ade <dump_pagetable+0x6e>
    80000ad0:	4481                	li	s1,0
    80000ad2:	2485                	addw	s1,s1,1
    80000ad4:	855a                	mv	a0,s6
    80000ad6:	f68ff0ef          	jal	8000023e <cprintf>
    80000ada:	ff549ce3          	bne	s1,s5,80000ad2 <dump_pagetable+0x62>
            cprintf("%s[%d]: PTE %p -> PA %p perm: ", 
    80000ade:	000c3583          	ld	a1,0(s8)
                   level_names[level], i, pte, PTE2PA(pte));
    80000ae2:	00a95493          	srl	s1,s2,0xa
            cprintf("%s[%d]: PTE %p -> PA %p perm: ", 
    80000ae6:	04b2                	sll	s1,s1,0xc
    80000ae8:	8726                	mv	a4,s1
    80000aea:	86ca                	mv	a3,s2
    80000aec:	864e                	mv	a2,s3
    80000aee:	8566                	mv	a0,s9
    80000af0:	f4eff0ef          	jal	8000023e <cprintf>
            if(pte & PTE_R) cprintf("R");
    80000af4:	00297793          	and	a5,s2,2
    80000af8:	efc9                	bnez	a5,80000b92 <dump_pagetable+0x122>
            if(pte & PTE_W) cprintf("W"); 
    80000afa:	00497793          	and	a5,s2,4
    80000afe:	e3d9                	bnez	a5,80000b84 <dump_pagetable+0x114>
            if(pte & PTE_X) cprintf("X");
    80000b00:	00897793          	and	a5,s2,8
    80000b04:	ebad                	bnez	a5,80000b76 <dump_pagetable+0x106>
            if(pte & PTE_U) cprintf("U");
    80000b06:	01097793          	and	a5,s2,16
    80000b0a:	efb9                	bnez	a5,80000b68 <dump_pagetable+0xf8>
            if(pte & PTE_G) cprintf("G");
    80000b0c:	02097793          	and	a5,s2,32
    80000b10:	e7a9                	bnez	a5,80000b5a <dump_pagetable+0xea>
            cprintf("\n");
    80000b12:	00001517          	auipc	a0,0x1
    80000b16:	56e50513          	add	a0,a0,1390 # 80002080 <_etext+0x80>
    80000b1a:	f24ff0ef          	jal	8000023e <cprintf>
            if(level > 0 && (pte & (PTE_R|PTE_W|PTE_X)) == 0) {
    80000b1e:	f9705ce3          	blez	s7,80000ab6 <dump_pagetable+0x46>
    80000b22:	00e97913          	and	s2,s2,14
    80000b26:	f80918e3          	bnez	s2,80000ab6 <dump_pagetable+0x46>
                dump_pagetable((pagetable_t)PTE2PA(pte), level - 1);
    80000b2a:	fffb859b          	addw	a1,s7,-1
    80000b2e:	8526                	mv	a0,s1
    80000b30:	f41ff0ef          	jal	80000a70 <dump_pagetable>
    for(int i = 0; i < 512; i++) {
    80000b34:	2985                	addw	s3,s3,1
    80000b36:	20000793          	li	a5,512
    80000b3a:	0a21                	add	s4,s4,8
    80000b3c:	f8f993e3          	bne	s3,a5,80000ac2 <dump_pagetable+0x52>
}
    80000b40:	60e6                	ld	ra,88(sp)
    80000b42:	6446                	ld	s0,80(sp)
    80000b44:	64a6                	ld	s1,72(sp)
    80000b46:	6906                	ld	s2,64(sp)
    80000b48:	79e2                	ld	s3,56(sp)
    80000b4a:	7a42                	ld	s4,48(sp)
    80000b4c:	7aa2                	ld	s5,40(sp)
    80000b4e:	7b02                	ld	s6,32(sp)
    80000b50:	6be2                	ld	s7,24(sp)
    80000b52:	6c42                	ld	s8,16(sp)
    80000b54:	6ca2                	ld	s9,8(sp)
    80000b56:	6125                	add	sp,sp,96
    80000b58:	8082                	ret
            if(pte & PTE_G) cprintf("G");
    80000b5a:	00001517          	auipc	a0,0x1
    80000b5e:	74e50513          	add	a0,a0,1870 # 800022a8 <_etext+0x2a8>
    80000b62:	edcff0ef          	jal	8000023e <cprintf>
    80000b66:	b775                	j	80000b12 <dump_pagetable+0xa2>
            if(pte & PTE_U) cprintf("U");
    80000b68:	00001517          	auipc	a0,0x1
    80000b6c:	73850513          	add	a0,a0,1848 # 800022a0 <_etext+0x2a0>
    80000b70:	eceff0ef          	jal	8000023e <cprintf>
    80000b74:	bf61                	j	80000b0c <dump_pagetable+0x9c>
            if(pte & PTE_X) cprintf("X");
    80000b76:	00001517          	auipc	a0,0x1
    80000b7a:	72250513          	add	a0,a0,1826 # 80002298 <_etext+0x298>
    80000b7e:	ec0ff0ef          	jal	8000023e <cprintf>
    80000b82:	b751                	j	80000b06 <dump_pagetable+0x96>
            if(pte & PTE_W) cprintf("W"); 
    80000b84:	00001517          	auipc	a0,0x1
    80000b88:	70c50513          	add	a0,a0,1804 # 80002290 <_etext+0x290>
    80000b8c:	eb2ff0ef          	jal	8000023e <cprintf>
    80000b90:	bf85                	j	80000b00 <dump_pagetable+0x90>
            if(pte & PTE_R) cprintf("R");
    80000b92:	00001517          	auipc	a0,0x1
    80000b96:	6f650513          	add	a0,a0,1782 # 80002288 <_etext+0x288>
    80000b9a:	ea4ff0ef          	jal	8000023e <cprintf>
    80000b9e:	bfb1                	j	80000afa <dump_pagetable+0x8a>

0000000080000ba0 <kvminit>:
{
    80000ba0:	1101                	add	sp,sp,-32
    80000ba2:	e822                	sd	s0,16(sp)
    80000ba4:	e426                	sd	s1,8(sp)
    80000ba6:	ec06                	sd	ra,24(sp)
    80000ba8:	e04a                	sd	s2,0(sp)
    80000baa:	1000                	add	s0,sp,32
    pagetable_t pt = (pagetable_t)alloc_page();
    80000bac:	396000ef          	jal	80000f42 <alloc_page>
    80000bb0:	84aa                	mv	s1,a0
    if(pt) {
    80000bb2:	c509                	beqz	a0,80000bbc <kvminit+0x1c>
        memset(pt, 0, PAGE_SIZE);
    80000bb4:	6605                	lui	a2,0x1
    80000bb6:	4581                	li	a1,0
    80000bb8:	9b1ff0ef          	jal	80000568 <memset>
    map_region(kernel_pagetable, KERNBASE, KERNBASE, 
    80000bbc:	4605                	li	a2,1
    80000bbe:	067e                	sll	a2,a2,0x1f
    kernel_pagetable = create_pagetable();
    80000bc0:	00003917          	auipc	s2,0x3
    80000bc4:	44090913          	add	s2,s2,1088 # 80004000 <kernel_pagetable>
    map_region(kernel_pagetable, KERNBASE, KERNBASE, 
    80000bc8:	85b2                	mv	a1,a2
    80000bca:	8526                	mv	a0,s1
    80000bcc:	4729                	li	a4,10
    80000bce:	80001697          	auipc	a3,0x80001
    80000bd2:	43268693          	add	a3,a3,1074 # 2000 <_start-0x7fffe000>
    kernel_pagetable = create_pagetable();
    80000bd6:	00993023          	sd	s1,0(s2)
    map_region(kernel_pagetable, KERNBASE, KERNBASE, 
    80000bda:	d2bff0ef          	jal	80000904 <map_region>
    map_region(kernel_pagetable, (uint64)etext, (uint64)etext,
    80000bde:	00093503          	ld	a0,0(s2)
    80000be2:	46c5                	li	a3,17
               (uint64)etext - KERNBASE, PTE_R | PTE_X);
    80000be4:	00001617          	auipc	a2,0x1
    80000be8:	41c60613          	add	a2,a2,1052 # 80002000 <_etext>
    map_region(kernel_pagetable, (uint64)etext, (uint64)etext,
    80000bec:	06ee                	sll	a3,a3,0x1b
    80000bee:	8e91                	sub	a3,a3,a2
    80000bf0:	85b2                	mv	a1,a2
    80000bf2:	4719                	li	a4,6
    80000bf4:	d11ff0ef          	jal	80000904 <map_region>
    map_region(kernel_pagetable, UART0, UART0, PAGE_SIZE, PTE_R | PTE_W);
    80000bf8:	00093503          	ld	a0,0(s2)
    80000bfc:	4719                	li	a4,6
    80000bfe:	6685                	lui	a3,0x1
    80000c00:	10000637          	lui	a2,0x10000
    80000c04:	100005b7          	lui	a1,0x10000
    80000c08:	cfdff0ef          	jal	80000904 <map_region>
    map_region(kernel_pagetable, VIRTIO0, VIRTIO0, PAGE_SIZE, PTE_R | PTE_W);
    80000c0c:	00093503          	ld	a0,0(s2)
    80000c10:	4719                	li	a4,6
    80000c12:	6685                	lui	a3,0x1
    80000c14:	10001637          	lui	a2,0x10001
    80000c18:	100015b7          	lui	a1,0x10001
    80000c1c:	ce9ff0ef          	jal	80000904 <map_region>
}
    80000c20:	6442                	ld	s0,16(sp)
    80000c22:	60e2                	ld	ra,24(sp)
    80000c24:	64a2                	ld	s1,8(sp)
    80000c26:	6902                	ld	s2,0(sp)
    cprintf("kvminit: kernel page table created\n");
    80000c28:	00001517          	auipc	a0,0x1
    80000c2c:	68850513          	add	a0,a0,1672 # 800022b0 <_etext+0x2b0>
}
    80000c30:	6105                	add	sp,sp,32
    cprintf("kvminit: kernel page table created\n");
    80000c32:	e0cff06f          	j	8000023e <cprintf>

0000000080000c36 <kvminithart>:
// SATP寄存器构造宏
//#define MAKE_SATP(pagetable) (8L << 60 | ((uint64)pagetable) >> 12)

// 激活内核页表
void kvminithart(void)
{
    80000c36:	1141                	add	sp,sp,-16
    80000c38:	e422                	sd	s0,8(sp)
    80000c3a:	0800                	add	s0,sp,16
    w_satp(MAKE_SATP(kernel_pagetable));
    80000c3c:	00003797          	auipc	a5,0x3
    80000c40:	3c47b783          	ld	a5,964(a5) # 80004000 <kernel_pagetable>
    80000c44:	577d                	li	a4,-1
    80000c46:	177e                	sll	a4,a4,0x3f
    80000c48:	83b1                	srl	a5,a5,0xc
    80000c4a:	8fd9                	or	a5,a5,a4
}

static inline void
w_satp(uint64 x)
{
    asm volatile("csrw satp, %0" :: "r"(x));
    80000c4c:	18079073          	csrw	satp,a5

// TLB屏障指令，用于刷新TLB[citation:10]
static inline void
sfence_vma()
{
    asm volatile("sfence.vma zero, zero");
    80000c50:	12000073          	sfence.vma
    sfence_vma(); // 刷新TLB
    
    cprintf("kvminithart: virtual memory enabled\n");
}
    80000c54:	6422                	ld	s0,8(sp)
    cprintf("kvminithart: virtual memory enabled\n");
    80000c56:	00001517          	auipc	a0,0x1
    80000c5a:	68250513          	add	a0,a0,1666 # 800022d8 <_etext+0x2d8>
}
    80000c5e:	0141                	add	sp,sp,16
    cprintf("kvminithart: virtual memory enabled\n");
    80000c60:	ddeff06f          	j	8000023e <cprintf>

0000000080000c64 <test_physical_memory>:
#include "memlayout.h"
#include "mmu.h"
#include "test_mem.h"

void test_physical_memory(void)
{
    80000c64:	1101                	add	sp,sp,-32
    80000c66:	ec06                	sd	ra,24(sp)
    80000c68:	e822                	sd	s0,16(sp)
    80000c6a:	e426                	sd	s1,8(sp)
    80000c6c:	1000                	add	s0,sp,32
    80000c6e:	e04a                	sd	s2,0(sp)
    cprintf("=== Testing Physical Memory Manager ===\n");
    80000c70:	00001517          	auipc	a0,0x1
    80000c74:	6c050513          	add	a0,a0,1728 # 80002330 <level_names.0+0x18>
    80000c78:	dc6ff0ef          	jal	8000023e <cprintf>
    
    pmm_stats();
    80000c7c:	544000ef          	jal	800011c0 <pmm_stats>
    
    // 测试基本分配
    void *page1 = alloc_page();
    80000c80:	2c2000ef          	jal	80000f42 <alloc_page>
    80000c84:	84aa                	mv	s1,a0
    void *page2 = alloc_page();
    80000c86:	2bc000ef          	jal	80000f42 <alloc_page>
    80000c8a:	892a                	mv	s2,a0
    
    if(page1 == 0 || page2 == 0) {
    80000c8c:	ccb1                	beqz	s1,80000ce8 <test_physical_memory+0x84>
    80000c8e:	c139                	beqz	a0,80000cd4 <test_physical_memory+0x70>
        panic("test_physical_memory: alloc_page failed");
    }
    
    if(page1 == page2) {
    80000c90:	06a48f63          	beq	s1,a0,80000d0e <test_physical_memory+0xaa>
        panic("test_physical_memory: duplicate page allocation");
    }
    
    // 测试页对齐
    if((uint64)page1 % PAGE_SIZE != 0 || (uint64)page2 % PAGE_SIZE != 0) {
    80000c94:	03449793          	sll	a5,s1,0x34
    80000c98:	c3a5                	beqz	a5,80000cf8 <test_physical_memory+0x94>
        panic("test_physical_memory: page not aligned");
    80000c9a:	00001517          	auipc	a0,0x1
    80000c9e:	71e50513          	add	a0,a0,1822 # 800023b8 <level_names.0+0xa0>
    80000ca2:	dd6ff0ef          	jal	80000278 <panic>
    }
    
    // 测试数据读写
    *(uint64*)page1 = 0x123456789ABCDEF0;
    80000ca6:	00002797          	auipc	a5,0x2
    80000caa:	9ba7b783          	ld	a5,-1606(a5) # 80002660 <level_names.0+0x348>
    80000cae:	e09c                	sd	a5,0(s1)
    if(*(uint64*)page1 != 0x123456789ABCDEF0) {
        panic("test_physical_memory: data write failed");
    }
    
    // 测试释放和重新分配
    free_page(page1);
    80000cb0:	8526                	mv	a0,s1
    80000cb2:	310000ef          	jal	80000fc2 <free_page>
    void *page3 = alloc_page();
    80000cb6:	28c000ef          	jal	80000f42 <alloc_page>
    
    pmm_stats();
    80000cba:	506000ef          	jal	800011c0 <pmm_stats>
    cprintf("Physical memory test passed!\n");
}
    80000cbe:	6442                	ld	s0,16(sp)
    80000cc0:	60e2                	ld	ra,24(sp)
    80000cc2:	64a2                	ld	s1,8(sp)
    80000cc4:	6902                	ld	s2,0(sp)
    cprintf("Physical memory test passed!\n");
    80000cc6:	00001517          	auipc	a0,0x1
    80000cca:	71a50513          	add	a0,a0,1818 # 800023e0 <level_names.0+0xc8>
}
    80000cce:	6105                	add	sp,sp,32
    cprintf("Physical memory test passed!\n");
    80000cd0:	d6eff06f          	j	8000023e <cprintf>
        panic("test_physical_memory: alloc_page failed");
    80000cd4:	00001517          	auipc	a0,0x1
    80000cd8:	68c50513          	add	a0,a0,1676 # 80002360 <level_names.0+0x48>
    80000cdc:	d9cff0ef          	jal	80000278 <panic>
    if((uint64)page1 % PAGE_SIZE != 0 || (uint64)page2 % PAGE_SIZE != 0) {
    80000ce0:	03449793          	sll	a5,s1,0x34
    80000ce4:	fbdd                	bnez	a5,80000c9a <test_physical_memory+0x36>
    80000ce6:	b7c1                	j	80000ca6 <test_physical_memory+0x42>
        panic("test_physical_memory: alloc_page failed");
    80000ce8:	00001517          	auipc	a0,0x1
    80000cec:	67850513          	add	a0,a0,1656 # 80002360 <level_names.0+0x48>
    80000cf0:	d88ff0ef          	jal	80000278 <panic>
    if(page1 == page2) {
    80000cf4:	00090663          	beqz	s2,80000d00 <test_physical_memory+0x9c>
    if((uint64)page1 % PAGE_SIZE != 0 || (uint64)page2 % PAGE_SIZE != 0) {
    80000cf8:	1952                	sll	s2,s2,0x34
    80000cfa:	fa0910e3          	bnez	s2,80000c9a <test_physical_memory+0x36>
    80000cfe:	b765                	j	80000ca6 <test_physical_memory+0x42>
        panic("test_physical_memory: duplicate page allocation");
    80000d00:	00001517          	auipc	a0,0x1
    80000d04:	68850513          	add	a0,a0,1672 # 80002388 <level_names.0+0x70>
    80000d08:	d70ff0ef          	jal	80000278 <panic>
    if((uint64)page1 % PAGE_SIZE != 0 || (uint64)page2 % PAGE_SIZE != 0) {
    80000d0c:	b7f5                	j	80000cf8 <test_physical_memory+0x94>
        panic("test_physical_memory: duplicate page allocation");
    80000d0e:	00001517          	auipc	a0,0x1
    80000d12:	67a50513          	add	a0,a0,1658 # 80002388 <level_names.0+0x70>
    80000d16:	d62ff0ef          	jal	80000278 <panic>
    80000d1a:	bfad                	j	80000c94 <test_physical_memory+0x30>

0000000080000d1c <test_pagetable>:

void test_pagetable(void)
{
    80000d1c:	7179                	add	sp,sp,-48
    80000d1e:	f406                	sd	ra,40(sp)
    80000d20:	f022                	sd	s0,32(sp)
    80000d22:	ec26                	sd	s1,24(sp)
    80000d24:	1800                	add	s0,sp,48
    80000d26:	e84a                	sd	s2,16(sp)
    80000d28:	e44e                	sd	s3,8(sp)
    cprintf("=== Testing Page Table Manager ===\n");
    80000d2a:	00001517          	auipc	a0,0x1
    80000d2e:	6d650513          	add	a0,a0,1750 # 80002400 <level_names.0+0xe8>
    80000d32:	d0cff0ef          	jal	8000023e <cprintf>
    
    pagetable_t pt = create_pagetable();
    80000d36:	a5dff0ef          	jal	80000792 <create_pagetable>
    80000d3a:	84aa                	mv	s1,a0
    if(pt == 0) {
    80000d3c:	c955                	beqz	a0,80000df0 <test_pagetable+0xd4>
        panic("test_pagetable: create_pagetable failed");
    }
    
    // 测试映射
    uint64 va = 0x1000000; // 测试虚拟地址
    uint64 pa = (uint64)alloc_page();
    80000d3e:	204000ef          	jal	80000f42 <alloc_page>
    80000d42:	89aa                	mv	s3,a0
    
    if(map_page(pt, va, pa, PTE_R | PTE_W) < 0) {
    80000d44:	862a                	mv	a2,a0
    80000d46:	4699                	li	a3,6
    80000d48:	010005b7          	lui	a1,0x1000
    80000d4c:	8526                	mv	a0,s1
    80000d4e:	c77ff0ef          	jal	800009c4 <map_page>
    80000d52:	0a054663          	bltz	a0,80000dfe <test_pagetable+0xe2>
        panic("test_pagetable: map_page failed");
    }
    
    // 测试地址转换
    pte_t *pte = walk_lookup(pt, va);
    80000d56:	010005b7          	lui	a1,0x1000
    80000d5a:	8526                	mv	a0,s1
    80000d5c:	acfff0ef          	jal	8000082a <walk_lookup>
    80000d60:	892a                	mv	s2,a0
    if(pte == 0 || !(*pte & PTE_V)) {
    80000d62:	cd35                	beqz	a0,80000dde <test_pagetable+0xc2>
    80000d64:	611c                	ld	a5,0(a0)
    80000d66:	0017f713          	and	a4,a5,1
    80000d6a:	cb35                	beqz	a4,80000dde <test_pagetable+0xc2>
        panic("test_pagetable: walk_lookup failed");
    }
    
    if(PTE2PA(*pte) != pa) {
    80000d6c:	00a7d713          	srl	a4,a5,0xa
    80000d70:	0732                	sll	a4,a4,0xc
    80000d72:	01370a63          	beq	a4,s3,80000d86 <test_pagetable+0x6a>
        panic("test_pagetable: address translation failed");
    80000d76:	00001517          	auipc	a0,0x1
    80000d7a:	72250513          	add	a0,a0,1826 # 80002498 <level_names.0+0x180>
    80000d7e:	cfaff0ef          	jal	80000278 <panic>
    }
    
    // 测试权限位
    if(!(*pte & PTE_R) || !(*pte & PTE_W)) {
    80000d82:	00093783          	ld	a5,0(s2)
    80000d86:	8b99                	and	a5,a5,6
    80000d88:	4719                	li	a4,6
    80000d8a:	00e78863          	beq	a5,a4,80000d9a <test_pagetable+0x7e>
        panic("test_pagetable: permission bits incorrect");
    80000d8e:	00001517          	auipc	a0,0x1
    80000d92:	73a50513          	add	a0,a0,1850 # 800024c8 <level_names.0+0x1b0>
    80000d96:	ce2ff0ef          	jal	80000278 <panic>
    }
    
    // 测试数据访问
    *(uint64*)va = 0xDEADBEEF;
    80000d9a:	37ab77b7          	lui	a5,0x37ab7
    80000d9e:	078a                	sll	a5,a5,0x2
    80000da0:	01000737          	lui	a4,0x1000
    80000da4:	eef78793          	add	a5,a5,-273 # 37ab6eef <_start-0x48549111>
    80000da8:	e31c                	sd	a5,0(a4)
    if(*(uint64*)va != 0xDEADBEEF) {
        panic("test_pagetable: data access through page table failed");
    }
    
    cprintf("Page table contents:\n");
    80000daa:	00001517          	auipc	a0,0x1
    80000dae:	74e50513          	add	a0,a0,1870 # 800024f8 <level_names.0+0x1e0>
    80000db2:	c8cff0ef          	jal	8000023e <cprintf>
    dump_pagetable(pt, 2);
    80000db6:	4589                	li	a1,2
    80000db8:	8526                	mv	a0,s1
    80000dba:	cb7ff0ef          	jal	80000a70 <dump_pagetable>
    
    free_pagetable(pt, 2);
    80000dbe:	8526                	mv	a0,s1
    80000dc0:	4589                	li	a1,2
    80000dc2:	9f7ff0ef          	jal	800007b8 <free_pagetable>
    cprintf("Page table test passed!\n");
}
    80000dc6:	7402                	ld	s0,32(sp)
    80000dc8:	70a2                	ld	ra,40(sp)
    80000dca:	64e2                	ld	s1,24(sp)
    80000dcc:	6942                	ld	s2,16(sp)
    80000dce:	69a2                	ld	s3,8(sp)
    cprintf("Page table test passed!\n");
    80000dd0:	00001517          	auipc	a0,0x1
    80000dd4:	74050513          	add	a0,a0,1856 # 80002510 <level_names.0+0x1f8>
}
    80000dd8:	6145                	add	sp,sp,48
    cprintf("Page table test passed!\n");
    80000dda:	c64ff06f          	j	8000023e <cprintf>
        panic("test_pagetable: walk_lookup failed");
    80000dde:	00001517          	auipc	a0,0x1
    80000de2:	69250513          	add	a0,a0,1682 # 80002470 <level_names.0+0x158>
    80000de6:	c92ff0ef          	jal	80000278 <panic>
    if(PTE2PA(*pte) != pa) {
    80000dea:	00093783          	ld	a5,0(s2)
    80000dee:	bfbd                	j	80000d6c <test_pagetable+0x50>
        panic("test_pagetable: create_pagetable failed");
    80000df0:	00001517          	auipc	a0,0x1
    80000df4:	63850513          	add	a0,a0,1592 # 80002428 <level_names.0+0x110>
    80000df8:	c80ff0ef          	jal	80000278 <panic>
    80000dfc:	b789                	j	80000d3e <test_pagetable+0x22>
        panic("test_pagetable: map_page failed");
    80000dfe:	00001517          	auipc	a0,0x1
    80000e02:	65250513          	add	a0,a0,1618 # 80002450 <level_names.0+0x138>
    80000e06:	c72ff0ef          	jal	80000278 <panic>
    80000e0a:	b7b1                	j	80000d56 <test_pagetable+0x3a>

0000000080000e0c <test_virtual_memory>:

void test_virtual_memory(void)
{
    80000e0c:	1141                	add	sp,sp,-16
    80000e0e:	e022                	sd	s0,0(sp)
    80000e10:	e406                	sd	ra,8(sp)
    80000e12:	0800                	add	s0,sp,16
    cprintf("=== Testing Virtual Memory ===\n");
    80000e14:	00001517          	auipc	a0,0x1
    80000e18:	71c50513          	add	a0,a0,1820 # 80002530 <level_names.0+0x218>
    80000e1c:	c22ff0ef          	jal	8000023e <cprintf>
    asm volatile("csrr %0, satp" : "=r"(x));
    80000e20:	180027f3          	csrr	a5,satp
    
    // 保存当前satp
    uint64 old_satp = r_satp();
    
    // 初始化并启用内核页表
    kvminit();
    80000e24:	d7dff0ef          	jal	80000ba0 <kvminit>
    kvminithart();
    80000e28:	e0fff0ef          	jal	80000c36 <kvminithart>
    
    // 测试内核功能仍然正常
    printf("Kernel is still alive after enabling paging!\n");
    80000e2c:	00001517          	auipc	a0,0x1
    80000e30:	72450513          	add	a0,a0,1828 # 80002550 <level_names.0+0x238>
    80000e34:	d96ff0ef          	jal	800003ca <printf>
    
    // 测试UART访问（通过设备映射）
    volatile uint32 *uart = (uint32*)UART0;
    uint32 uart_value = uart[0]; // 读取UART寄存器
    80000e38:	100007b7          	lui	a5,0x10000
    80000e3c:	438c                	lw	a1,0(a5)
    
    printf("UART access through virtual memory: 0x%x\n", uart_value);
    80000e3e:	00001517          	auipc	a0,0x1
    80000e42:	74250513          	add	a0,a0,1858 # 80002580 <level_names.0+0x268>
    80000e46:	d84ff0ef          	jal	800003ca <printf>
    // 恢复原页表（如果需要）
    // w_satp(old_satp);
    // sfence_vma();
    
    printf("Virtual memory test passed!\n");
    80000e4a:	6402                	ld	s0,0(sp)
    80000e4c:	60a2                	ld	ra,8(sp)
    printf("Virtual memory test passed!\n");
    80000e4e:	00001517          	auipc	a0,0x1
    80000e52:	76250513          	add	a0,a0,1890 # 800025b0 <level_names.0+0x298>
    80000e56:	0141                	add	sp,sp,16
    printf("Virtual memory test passed!\n");
    80000e58:	d72ff06f          	j	800003ca <printf>

0000000080000e5c <initlock>:
#include "spinlock.h"

// 初始化自旋锁函数
void initlock(spinlock_t *lock, char *name) {
    80000e5c:	1141                	add	sp,sp,-16
    80000e5e:	e422                	sd	s0,8(sp)
    80000e60:	0800                	add	s0,sp,16
    lock->locked = 0;
    lock->name = name;
}
    80000e62:	6422                	ld	s0,8(sp)
    lock->locked = 0;
    80000e64:	00050023          	sb	zero,0(a0)
    lock->name = name;
    80000e68:	e50c                	sd	a1,8(a0)
}
    80000e6a:	0141                	add	sp,sp,16
    80000e6c:	8082                	ret

0000000080000e6e <spin_lock>:

// 获取自旋锁
void spin_lock(spinlock_t *lock) {
    80000e6e:	1141                	add	sp,sp,-16
    80000e70:	00357713          	and	a4,a0,3
    80000e74:	e422                	sd	s0,8(sp)
    // 使用原子操作尝试获取锁，避免多核竞争 [citation:8]
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000e76:	0037171b          	sllw	a4,a4,0x3
void spin_lock(spinlock_t *lock) {
    80000e7a:	0800                	add	s0,sp,16
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000e7c:	4685                	li	a3,1
void spin_lock(spinlock_t *lock) {
    80000e7e:	9971                	and	a0,a0,-4
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000e80:	00e696bb          	sllw	a3,a3,a4
    80000e84:	4605                	li	a2,1
    80000e86:	a011                	j	80000e8a <spin_lock+0x1c>
        // 锁被占用时，让CPU核心短暂休息（对于RISC-V，可使用wfi指令或直接循环）
        asm volatile("nop"); // 简单的空操作，避免过度消耗
    80000e88:	0001                	nop
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000e8a:	44d527af          	amoor.w.aq	a5,a3,(a0)
    80000e8e:	00e7d7bb          	srlw	a5,a5,a4
    80000e92:	0ff7f793          	zext.b	a5,a5
    80000e96:	fec789e3          	beq	a5,a2,80000e88 <spin_lock+0x1a>
    }
    // 内存屏障，确保临界区内的负载和存储不会越过此边界 [citation:5]
    __sync_synchronize();
    80000e9a:	0ff0000f          	fence
}
    80000e9e:	6422                	ld	s0,8(sp)
    80000ea0:	0141                	add	sp,sp,16
    80000ea2:	8082                	ret

0000000080000ea4 <spin_trylock>:

// 尝试获取自旋锁
int spin_trylock(spinlock_t *lock) {
    80000ea4:	1141                	add	sp,sp,-16
    // 原子性地尝试将锁设置为1，并返回旧值 [citation:4]
    if (__sync_lock_test_and_set(&lock->locked, 1) == 0) {
    80000ea6:	00357713          	and	a4,a0,3
int spin_trylock(spinlock_t *lock) {
    80000eaa:	e422                	sd	s0,8(sp)
    if (__sync_lock_test_and_set(&lock->locked, 1) == 0) {
    80000eac:	0037171b          	sllw	a4,a4,0x3
int spin_trylock(spinlock_t *lock) {
    80000eb0:	0800                	add	s0,sp,16
    if (__sync_lock_test_and_set(&lock->locked, 1) == 0) {
    80000eb2:	4685                	li	a3,1
    80000eb4:	9971                	and	a0,a0,-4
    80000eb6:	00e696bb          	sllw	a3,a3,a4
    80000eba:	44d527af          	amoor.w.aq	a5,a3,(a0)
    80000ebe:	00e7d7bb          	srlw	a5,a5,a4
    80000ec2:	0ff7f793          	zext.b	a5,a5
        __sync_synchronize(); // 获取成功，添加内存屏障
        return 0; // 成功
    }
    return 1; // 失败
    80000ec6:	4505                	li	a0,1
    if (__sync_lock_test_and_set(&lock->locked, 1) == 0) {
    80000ec8:	c781                	beqz	a5,80000ed0 <spin_trylock+0x2c>
}
    80000eca:	6422                	ld	s0,8(sp)
    80000ecc:	0141                	add	sp,sp,16
    80000ece:	8082                	ret
        __sync_synchronize(); // 获取成功，添加内存屏障
    80000ed0:	0ff0000f          	fence
}
    80000ed4:	6422                	ld	s0,8(sp)
        return 0; // 成功
    80000ed6:	4501                	li	a0,0
}
    80000ed8:	0141                	add	sp,sp,16
    80000eda:	8082                	ret

0000000080000edc <spin_unlock>:

// 释放自旋锁
void spin_unlock(spinlock_t *lock) {
    80000edc:	1141                	add	sp,sp,-16
    80000ede:	e422                	sd	s0,8(sp)
    80000ee0:	0800                	add	s0,sp,16
    __sync_synchronize(); // 释放前的内存屏障
    80000ee2:	0ff0000f          	fence
    // 原子性地释放锁 [citation:4]
    __sync_lock_release(&lock->locked);
    80000ee6:	0ff0000f          	fence
    80000eea:	00050023          	sb	zero,0(a0)
}
    80000eee:	6422                	ld	s0,8(sp)
    80000ef0:	0141                	add	sp,sp,16
    80000ef2:	8082                	ret

0000000080000ef4 <acquire>:

// 为兼容性创建别名
void acquire(spinlock_t *lock) {
    80000ef4:	1141                	add	sp,sp,-16
    80000ef6:	00357713          	and	a4,a0,3
    80000efa:	e422                	sd	s0,8(sp)
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000efc:	0037171b          	sllw	a4,a4,0x3
void acquire(spinlock_t *lock) {
    80000f00:	0800                	add	s0,sp,16
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000f02:	4685                	li	a3,1
void acquire(spinlock_t *lock) {
    80000f04:	9971                	and	a0,a0,-4
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000f06:	00e696bb          	sllw	a3,a3,a4
    80000f0a:	4605                	li	a2,1
    80000f0c:	a011                	j	80000f10 <acquire+0x1c>
        asm volatile("nop"); // 简单的空操作，避免过度消耗
    80000f0e:	0001                	nop
    while (__sync_lock_test_and_set(&lock->locked, 1) == 1) {
    80000f10:	44d527af          	amoor.w.aq	a5,a3,(a0)
    80000f14:	00e7d7bb          	srlw	a5,a5,a4
    80000f18:	0ff7f793          	zext.b	a5,a5
    80000f1c:	fec789e3          	beq	a5,a2,80000f0e <acquire+0x1a>
    __sync_synchronize();
    80000f20:	0ff0000f          	fence
    spin_lock(lock);
}
    80000f24:	6422                	ld	s0,8(sp)
    80000f26:	0141                	add	sp,sp,16
    80000f28:	8082                	ret

0000000080000f2a <release>:

void release(spinlock_t *lock) {
    80000f2a:	1141                	add	sp,sp,-16
    80000f2c:	e422                	sd	s0,8(sp)
    80000f2e:	0800                	add	s0,sp,16
    80000f30:	0ff0000f          	fence
    80000f34:	0ff0000f          	fence
    80000f38:	00050023          	sb	zero,0(a0)
    80000f3c:	6422                	ld	s0,8(sp)
    80000f3e:	0141                	add	sp,sp,16
    80000f40:	8082                	ret

0000000080000f42 <alloc_page>:
    }
}

// 分配单页
void* alloc_page(void)
{
    80000f42:	1101                	add	sp,sp,-32
    80000f44:	e822                	sd	s0,16(sp)
    80000f46:	e426                	sd	s1,8(sp)
    80000f48:	e04a                	sd	s2,0(sp)
    80000f4a:	ec06                	sd	ra,24(sp)
    80000f4c:	1000                	add	s0,sp,32
    acquire(&pmm.lock);
    80000f4e:	00001497          	auipc	s1,0x1
    80000f52:	71a48493          	add	s1,s1,1818 # 80002668 <pmm>
    80000f56:	8526                	mv	a0,s1
    80000f58:	f9dff0ef          	jal	80000ef4 <acquire>
    
    if(pmm.freelist == 0) {
    80000f5c:	0104b903          	ld	s2,16(s1)
    80000f60:	04090863          	beqz	s2,80000fb0 <alloc_page+0x6e>
        panic("alloc_page: out of memory");
    }
    
    struct run *r = pmm.freelist;
    pmm.freelist = r->next;
    pmm.free_pages--;
    80000f64:	7094                	ld	a3,32(s1)
    pmm.freelist = r->next;
    80000f66:	00093583          	ld	a1,0(s2)
    
    // 标记页面为已分配
    uint64 page_index = ((uint64)r - KERNBASE) / PAGE_SIZE;
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f6a:	7498                	ld	a4,40(s1)
    uint64 page_index = ((uint64)r - KERNBASE) / PAGE_SIZE;
    80000f6c:	800007b7          	lui	a5,0x80000
    80000f70:	97ca                	add	a5,a5,s2
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f72:	00f7d613          	srl	a2,a5,0xf
    pmm.free_pages--;
    80000f76:	16fd                	add	a3,a3,-1 # fff <_start-0x7ffff001>
    pmm.freelist = r->next;
    80000f78:	e88c                	sd	a1,16(s1)
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f7a:	9732                	add	a4,a4,a2
    pmm.free_pages--;
    80000f7c:	f094                	sd	a3,32(s1)
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f7e:	00074683          	lbu	a3,0(a4) # 1000000 <_start-0x7f000000>
    uint64 page_index = ((uint64)r - KERNBASE) / PAGE_SIZE;
    80000f82:	83b1                	srl	a5,a5,0xc
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f84:	4605                	li	a2,1
    80000f86:	8b9d                	and	a5,a5,7
    80000f88:	00f617bb          	sllw	a5,a2,a5
    80000f8c:	8fd5                	or	a5,a5,a3
    
    // 清空页面内容
    memset(r, 0, PAGE_SIZE);
    80000f8e:	6605                	lui	a2,0x1
    80000f90:	4581                	li	a1,0
    pmm.page_allocated[page_index / 8] |= (1 << (page_index % 8));
    80000f92:	00f70023          	sb	a5,0(a4)
    memset(r, 0, PAGE_SIZE);
    80000f96:	854a                	mv	a0,s2
    80000f98:	dd0ff0ef          	jal	80000568 <memset>
    
    release(&pmm.lock);
    80000f9c:	8526                	mv	a0,s1
    80000f9e:	f8dff0ef          	jal	80000f2a <release>
    return (void*)r;
}
    80000fa2:	60e2                	ld	ra,24(sp)
    80000fa4:	6442                	ld	s0,16(sp)
    80000fa6:	64a2                	ld	s1,8(sp)
    80000fa8:	854a                	mv	a0,s2
    80000faa:	6902                	ld	s2,0(sp)
    80000fac:	6105                	add	sp,sp,32
    80000fae:	8082                	ret
        release(&pmm.lock);
    80000fb0:	8526                	mv	a0,s1
    80000fb2:	f79ff0ef          	jal	80000f2a <release>
        panic("alloc_page: out of memory");
    80000fb6:	00001517          	auipc	a0,0x1
    80000fba:	61a50513          	add	a0,a0,1562 # 800025d0 <level_names.0+0x2b8>
    80000fbe:	abaff0ef          	jal	80000278 <panic>

0000000080000fc2 <free_page>:

// 释放页面
void free_page(void *page)
{
    80000fc2:	7179                	add	sp,sp,-48
    80000fc4:	f022                	sd	s0,32(sp)
    80000fc6:	f406                	sd	ra,40(sp)
    80000fc8:	ec26                	sd	s1,24(sp)
    80000fca:	e84a                	sd	s2,16(sp)
    80000fcc:	e44e                	sd	s3,8(sp)
    80000fce:	1800                	add	s0,sp,48
    if((uint64)page % PAGE_SIZE != 0 || (uint64)page < KERNBASE || 
    80000fd0:	03451793          	sll	a5,a0,0x34
    80000fd4:	e7a5                	bnez	a5,8000103c <free_page+0x7a>
    80000fd6:	800004b7          	lui	s1,0x80000
    80000fda:	94aa                	add	s1,s1,a0
    80000fdc:	080007b7          	lui	a5,0x8000
    80000fe0:	89aa                	mv	s3,a0
    80000fe2:	04f4fd63          	bgeu	s1,a5,8000103c <free_page+0x7a>
       (uint64)page >= PHYSTOP) {
        panic("free_page: invalid page");
    }
    
    acquire(&pmm.lock);
    80000fe6:	00001917          	auipc	s2,0x1
    80000fea:	68290913          	add	s2,s2,1666 # 80002668 <pmm>
    80000fee:	854a                	mv	a0,s2
    80000ff0:	f05ff0ef          	jal	80000ef4 <acquire>
    
    // 标记页面为未分配
    uint64 page_index = ((uint64)page - KERNBASE) / PAGE_SIZE;
    pmm.page_allocated[page_index / 8] &= ~(1 << (page_index % 8));
    80000ff4:	02893703          	ld	a4,40(s2)
    80000ff8:	00f4d793          	srl	a5,s1,0xf
    uint64 page_index = ((uint64)page - KERNBASE) / PAGE_SIZE;
    80000ffc:	80b1                	srl	s1,s1,0xc
    pmm.page_allocated[page_index / 8] &= ~(1 << (page_index % 8));
    80000ffe:	973e                	add	a4,a4,a5
    80001000:	00074683          	lbu	a3,0(a4)
    80001004:	889d                	and	s1,s1,7
    80001006:	4785                	li	a5,1
    80001008:	009797bb          	sllw	a5,a5,s1
    8000100c:	fff7c793          	not	a5,a5
    80001010:	8ff5                	and	a5,a5,a3
    80001012:	00f70023          	sb	a5,0(a4)
    
    struct run *r = (struct run*)page;
    r->next = pmm.freelist;
    pmm.freelist = r;
    pmm.free_pages++;
    80001016:	02093783          	ld	a5,32(s2)
    r->next = pmm.freelist;
    8000101a:	01093703          	ld	a4,16(s2)
    
    release(&pmm.lock);
}
    8000101e:	7402                	ld	s0,32(sp)
    pmm.free_pages++;
    80001020:	0785                	add	a5,a5,1 # 8000001 <_start-0x77ffffff>
    r->next = pmm.freelist;
    80001022:	00e9b023          	sd	a4,0(s3)
    pmm.freelist = r;
    80001026:	01393823          	sd	s3,16(s2)
}
    8000102a:	70a2                	ld	ra,40(sp)
    8000102c:	64e2                	ld	s1,24(sp)
    8000102e:	69a2                	ld	s3,8(sp)
    pmm.free_pages++;
    80001030:	02f93023          	sd	a5,32(s2)
    release(&pmm.lock);
    80001034:	854a                	mv	a0,s2
}
    80001036:	6942                	ld	s2,16(sp)
    80001038:	6145                	add	sp,sp,48
    release(&pmm.lock);
    8000103a:	bdc5                	j	80000f2a <release>
        panic("free_page: invalid page");
    8000103c:	00001517          	auipc	a0,0x1
    80001040:	5b450513          	add	a0,a0,1460 # 800025f0 <level_names.0+0x2d8>
    80001044:	a34ff0ef          	jal	80000278 <panic>

0000000080001048 <freerange>:
    char *p = (char*)PGROUNDUP((uint64)vstart);
    80001048:	6785                	lui	a5,0x1
    8000104a:	fff78713          	add	a4,a5,-1 # fff <_start-0x7ffff001>
{
    8000104e:	7179                	add	sp,sp,-48
    char *p = (char*)PGROUNDUP((uint64)vstart);
    80001050:	953a                	add	a0,a0,a4
    80001052:	777d                	lui	a4,0xfffff
{
    80001054:	f022                	sd	s0,32(sp)
    80001056:	ec26                	sd	s1,24(sp)
    80001058:	f406                	sd	ra,40(sp)
    8000105a:	e84a                	sd	s2,16(sp)
    8000105c:	e44e                	sd	s3,8(sp)
    8000105e:	e052                	sd	s4,0(sp)
    80001060:	1800                	add	s0,sp,48
    char *p = (char*)PGROUNDUP((uint64)vstart);
    80001062:	8d79                	and	a0,a0,a4
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    80001064:	00f504b3          	add	s1,a0,a5
    80001068:	0095ec63          	bltu	a1,s1,80001080 <freerange+0x38>
    8000106c:	892e                	mv	s2,a1
        free_page(p);
    8000106e:	7a7d                	lui	s4,0xfffff
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    80001070:	6985                	lui	s3,0x1
        free_page(p);
    80001072:	01448533          	add	a0,s1,s4
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    80001076:	94ce                	add	s1,s1,s3
        free_page(p);
    80001078:	f4bff0ef          	jal	80000fc2 <free_page>
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    8000107c:	fe997be3          	bgeu	s2,s1,80001072 <freerange+0x2a>
}
    80001080:	70a2                	ld	ra,40(sp)
    80001082:	7402                	ld	s0,32(sp)
    80001084:	64e2                	ld	s1,24(sp)
    80001086:	6942                	ld	s2,16(sp)
    80001088:	69a2                	ld	s3,8(sp)
    8000108a:	6a02                	ld	s4,0(sp)
    8000108c:	6145                	add	sp,sp,48
    8000108e:	8082                	ret

0000000080001090 <pmm_init>:
{ 
    80001090:	7179                	add	sp,sp,-48
    80001092:	f022                	sd	s0,32(sp)
    80001094:	ec26                	sd	s1,24(sp)
    80001096:	e84a                	sd	s2,16(sp)
    80001098:	e052                	sd	s4,0(sp)
    8000109a:	f406                	sd	ra,40(sp)
    initlock(&pmm.lock, "pmm");
    8000109c:	00001a17          	auipc	s4,0x1
    800010a0:	5cca0a13          	add	s4,s4,1484 # 80002668 <pmm>
{ 
    800010a4:	e44e                	sd	s3,8(sp)
    800010a6:	1800                	add	s0,sp,48
    initlock(&pmm.lock, "pmm");
    800010a8:	00001597          	auipc	a1,0x1
    800010ac:	56058593          	add	a1,a1,1376 # 80002608 <level_names.0+0x2f0>
    800010b0:	8552                	mv	a0,s4
    800010b2:	dabff0ef          	jal	80000e5c <initlock>
    uint64 start = PGROUNDUP((uint64)end);
    800010b6:	75fd                	lui	a1,0xfffff
    800010b8:	00002797          	auipc	a5,0x2
    800010bc:	5df78793          	add	a5,a5,1503 # 80003697 <stack_bottom+0x697>
    pmm.total_pages = (end_mem - start) / PAGE_SIZE;
    800010c0:	4945                	li	s2,17
    uint64 start = PGROUNDUP((uint64)end);
    800010c2:	8fed                	and	a5,a5,a1
    pmm.total_pages = (end_mem - start) / PAGE_SIZE;
    800010c4:	096e                	sll	s2,s2,0x1b
    800010c6:	40f906b3          	sub	a3,s2,a5
    800010ca:	82b1                	srl	a3,a3,0xc
    uint64 start = PGROUNDUP((uint64)end);
    800010cc:	6705                	lui	a4,0x1
    uint64 bitmap_size = (pmm.total_pages + 7) / 8;
    800010ce:	00768493          	add	s1,a3,7
    uint64 start = PGROUNDUP((uint64)end);
    800010d2:	fff70613          	add	a2,a4,-1 # fff <_start-0x7ffff001>
    uint64 bitmap_size = (pmm.total_pages + 7) / 8;
    800010d6:	808d                	srl	s1,s1,0x3
    start += PGROUNDUP(bitmap_size);
    800010d8:	94b2                	add	s1,s1,a2
    800010da:	8ced                	and	s1,s1,a1
    char *p = (char*)PGROUNDUP((uint64)vstart);
    800010dc:	963e                	add	a2,a2,a5
    800010de:	94b2                	add	s1,s1,a2
    800010e0:	8ced                	and	s1,s1,a1
    pmm.total_pages = (end_mem - start) / PAGE_SIZE;
    800010e2:	00da3c23          	sd	a3,24(s4)
    pmm.page_allocated = (uint8*)start;
    800010e6:	02fa3423          	sd	a5,40(s4)
    pmm.free_pages = 0;
    800010ea:	00001697          	auipc	a3,0x1
    800010ee:	5806bf23          	sd	zero,1438(a3) # 80002688 <pmm+0x20>
    pmm.freelist = 0;
    800010f2:	00001797          	auipc	a5,0x1
    800010f6:	5807b323          	sd	zero,1414(a5) # 80002678 <pmm+0x10>
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    800010fa:	9726                	add	a4,a4,s1
    800010fc:	02e96863          	bltu	s2,a4,8000112c <pmm_init+0x9c>
    80001100:	6985                	lui	s3,0x1
        free_page(p);
    80001102:	8526                	mv	a0,s1
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    80001104:	94ce                	add	s1,s1,s3
        free_page(p);
    80001106:	ebdff0ef          	jal	80000fc2 <free_page>
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    8000110a:	ff249ce3          	bne	s1,s2,80001102 <pmm_init+0x72>
    cprintf("pmm: initialized, %d pages available\n", pmm.free_pages);
    8000110e:	020a3583          	ld	a1,32(s4)
}
    80001112:	7402                	ld	s0,32(sp)
    80001114:	70a2                	ld	ra,40(sp)
    80001116:	64e2                	ld	s1,24(sp)
    80001118:	6942                	ld	s2,16(sp)
    8000111a:	69a2                	ld	s3,8(sp)
    8000111c:	6a02                	ld	s4,0(sp)
    cprintf("pmm: initialized, %d pages available\n", pmm.free_pages);
    8000111e:	00001517          	auipc	a0,0x1
    80001122:	4f250513          	add	a0,a0,1266 # 80002610 <level_names.0+0x2f8>
}
    80001126:	6145                	add	sp,sp,48
    cprintf("pmm: initialized, %d pages available\n", pmm.free_pages);
    80001128:	916ff06f          	j	8000023e <cprintf>
    for(; p + PAGE_SIZE <= (char*)vend; p += PAGE_SIZE) {
    8000112c:	4581                	li	a1,0
    8000112e:	b7d5                	j	80001112 <pmm_init+0x82>

0000000080001130 <alloc_pages>:

// 分配连续页面
void* alloc_pages(int n)
{
    80001130:	7139                	add	sp,sp,-64
    80001132:	f822                	sd	s0,48(sp)
    80001134:	f426                	sd	s1,40(sp)
    80001136:	fc06                	sd	ra,56(sp)
    80001138:	f04a                	sd	s2,32(sp)
    8000113a:	ec4e                	sd	s3,24(sp)
    8000113c:	e852                	sd	s4,16(sp)
    8000113e:	e456                	sd	s5,8(sp)
    80001140:	0080                	add	s0,sp,64
    if(n <= 0) return 0;
    80001142:	4481                	li	s1,0
    80001144:	06a05163          	blez	a0,800011a6 <alloc_pages+0x76>
    80001148:	8a2a                	mv	s4,a0
    
    acquire(&pmm.lock);
    8000114a:	00001517          	auipc	a0,0x1
    8000114e:	51e50513          	add	a0,a0,1310 # 80002668 <pmm>
    80001152:	da3ff0ef          	jal	80000ef4 <acquire>
    
    // 简单实现：多次分配单页（实际应该使用更高效的算法）
    void *result = 0;
    void **pages = (void**)alloc_page(); // 临时存储分配的页面
    80001156:	dedff0ef          	jal	80000f42 <alloc_page>
    8000115a:	8aaa                	mv	s5,a0
    
    if(pages) {
    8000115c:	cd15                	beqz	a0,80001198 <alloc_pages+0x68>
    8000115e:	89aa                	mv	s3,a0
    80001160:	892a                	mv	s2,a0
        int i;
        for(i = 0; i < n; i++) {
    80001162:	4481                	li	s1,0
    80001164:	a029                	j	8000116e <alloc_pages+0x3e>
    80001166:	2485                	addw	s1,s1,1 # ffffffff80000001 <kernel_pagetable+0xfffffffeffffc001>
    80001168:	0921                	add	s2,s2,8
    8000116a:	049a0863          	beq	s4,s1,800011ba <alloc_pages+0x8a>
            pages[i] = alloc_page();
    8000116e:	dd5ff0ef          	jal	80000f42 <alloc_page>
    80001172:	00a93023          	sd	a0,0(s2)
            if(!pages[i]) break;
    80001176:	f965                	bnez	a0,80001166 <alloc_pages+0x36>
        }
        
        if(i == n) {
    80001178:	049a0163          	beq	s4,s1,800011ba <alloc_pages+0x8a>
            result = pages[0];
            // 确保连续性（这里简化处理）
        } else {
            // 分配失败，释放已分配的页面
            for(int j = 0; j < i; j++) {
    8000117c:	00349913          	sll	s2,s1,0x3
    80001180:	9956                	add	s2,s2,s5
    80001182:	c881                	beqz	s1,80001192 <alloc_pages+0x62>
                free_page(pages[j]);
    80001184:	0009b503          	ld	a0,0(s3) # 1000 <_start-0x7ffff000>
            for(int j = 0; j < i; j++) {
    80001188:	09a1                	add	s3,s3,8
                free_page(pages[j]);
    8000118a:	e39ff0ef          	jal	80000fc2 <free_page>
            for(int j = 0; j < i; j++) {
    8000118e:	ff391be3          	bne	s2,s3,80001184 <alloc_pages+0x54>
            }
            free_page(pages);
    80001192:	8556                	mv	a0,s5
    80001194:	e2fff0ef          	jal	80000fc2 <free_page>
    void *result = 0;
    80001198:	4481                	li	s1,0
        }
    }
    
    release(&pmm.lock);
    8000119a:	00001517          	auipc	a0,0x1
    8000119e:	4ce50513          	add	a0,a0,1230 # 80002668 <pmm>
    800011a2:	d89ff0ef          	jal	80000f2a <release>
    return result;
}
    800011a6:	70e2                	ld	ra,56(sp)
    800011a8:	7442                	ld	s0,48(sp)
    800011aa:	7902                	ld	s2,32(sp)
    800011ac:	69e2                	ld	s3,24(sp)
    800011ae:	6a42                	ld	s4,16(sp)
    800011b0:	6aa2                	ld	s5,8(sp)
    800011b2:	8526                	mv	a0,s1
    800011b4:	74a2                	ld	s1,40(sp)
    800011b6:	6121                	add	sp,sp,64
    800011b8:	8082                	ret
            result = pages[0];
    800011ba:	000ab483          	ld	s1,0(s5)
    800011be:	bff1                	j	8000119a <alloc_pages+0x6a>

00000000800011c0 <pmm_stats>:

// 内存统计
void pmm_stats(void)
{
    800011c0:	1101                	add	sp,sp,-32
    800011c2:	ec06                	sd	ra,24(sp)
    800011c4:	e822                	sd	s0,16(sp)
    800011c6:	e426                	sd	s1,8(sp)
    800011c8:	1000                	add	s0,sp,32
    acquire(&pmm.lock);
    800011ca:	00001497          	auipc	s1,0x1
    800011ce:	49e48493          	add	s1,s1,1182 # 80002668 <pmm>
    800011d2:	8526                	mv	a0,s1
    800011d4:	d21ff0ef          	jal	80000ef4 <acquire>
    cprintf("pmm: total pages: %d, free pages: %d\n", 
    800011d8:	7090                	ld	a2,32(s1)
    800011da:	6c8c                	ld	a1,24(s1)
    800011dc:	00001517          	auipc	a0,0x1
    800011e0:	45c50513          	add	a0,a0,1116 # 80002638 <level_names.0+0x320>
    800011e4:	85aff0ef          	jal	8000023e <cprintf>
            pmm.total_pages, pmm.free_pages);
    release(&pmm.lock);
    800011e8:	6442                	ld	s0,16(sp)
    800011ea:	60e2                	ld	ra,24(sp)
    release(&pmm.lock);
    800011ec:	8526                	mv	a0,s1
    800011ee:	64a2                	ld	s1,8(sp)
    800011f0:	6105                	add	sp,sp,32
    release(&pmm.lock);
    800011f2:	bb25                	j	80000f2a <release>
	...
